快捷搜索:  汽车  科技

msp430单片机的定时模式有哪几种(用MSP430的eUSCI模块的I2C协议读写EEPROM)

msp430单片机的定时模式有哪几种(用MSP430的eUSCI模块的I2C协议读写EEPROM)UCB0I2CSA写入从站地址,设置UCTXSTT标志位(发送START),eUSCI退出复位状态,进入工作模式,eUSCI等待总线空闲,发送START,和Slave Address,然后接收从站返回的数据,数据接收完,发送STOP。主站接收:eUSCI的I2C功能框图主站发送:UCB0I2CSA写入从站地址,设置UCTXSTT标志位(发送START),eUSCI退出复位状态,进入工作模式,eUSCI等待总线空闲,发送START,和Slave Address,以及后续数据,数据发送完后,发送STOP。

本文利用MSP430芯片eUSCI模块的I2C协议,来实现读写24CL04。

eUSCI模块通过SDA SCL与I2C设备相连接,模块主要具有以下功能:

  • 7位 和 10位地址可选
  • 多主站的收发模式
  • 从站收发模式
  • 通讯速率从100kbps到400kbps
  • 具备字节计数器,自动产生中断和自动发送STOP信号
  • 共有4个从站地址,每个都有对应的中断和DMA

本实验将MSP430F6736作为主站,24CL04作为从站。一主一从的模式,比较简单直观。

如果有需要,以后可以做多主对多从的模式。

msp430单片机的定时模式有哪几种(用MSP430的eUSCI模块的I2C协议读写EEPROM)(1)

eUSCI的I2C功能框图

主站发送:

UCB0I2CSA写入从站地址,设置UCTXSTT标志位(发送START),eUSCI退出复位状态,进入工作模式,eUSCI等待总线空闲,发送START,和Slave Address,以及后续数据,数据发送完后,发送STOP。

主站接收:

UCB0I2CSA写入从站地址,设置UCTXSTT标志位(发送START),eUSCI退出复位状态,进入工作模式,eUSCI等待总线空闲,发送START,和Slave Address,然后接收从站返回的数据,数据接收完,发送STOP。

在用I2C读写EEPROM的时候,MCU内相关的寄存器的一些位标志着通讯的状态,可以查询这些状态决定下一步操作。

但本文没有如此操作,因为比较复杂且具有风险,因为等待某标志位的时候必须设定超时,因为通讯不可能没有错误,一旦等不来需要的状态,又没有设定超时,程序很容易陷入死循环,这是绝对不允许发生的。所以采取延时的方式来处理,通讯波特率一旦确定,每个字节传输的时间就可以确定,再加上一点冗余,向发送寄存器写入数据后,等待固定的时间,继续发送下个字节。这样传输过程不会造成死机,数据的纠错可以在整包接收到后进行。

如果网友有更好的方式,欢迎评论留言。

以下为源码和演示视频:

#include "msp430.h" #include "msp430f6736a.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "math.h" #define uchar unsigned char #define uint unsigned int //--------------------------------- // 初始化MCU //--------------------------------- void Mcu_Init(void) { //--------------------------------- // 初始化系统时钟 //--------------------------------- WDTCTL = WDTPW WDTHOLD; // 禁止看门狗 __bic_SR_register(GIE); // 禁止所有中断 PMMCTL0 = PMMPW PMMCOREV_3; __delay_cycles(10000); // 初始化XT1 并使其正常工作 UCSCTL6 &= ~(XT1OFF XT1BYPASS XTS); UCSCTL6 |= XT1DRIVE_3; UCSCTL6 |= XCAP_3; do { UCSCTL7 &= ~XT1LFOFFG; __delay_cycles(30); } while (UCSCTL7 & XT1LFOFFG); // XT1CLK作为DCO输入 UCSCTL3 = SELREF__XT1CLK FLLREFDIV__1; // 禁止 FLL 控制 __bis_SR_register(SCG0); // DCO=31 MOD=0 UCSCTL0 = 0x1f00; // DCO 范围: 23.7MHz - 54.1MHz UCSCTL1 = DCORSEL_5; // fDCO分频系数D = 2 N = 374 // fDCOCLK = D * (N 1) * FLLRef = 2 * (374 1) * 32768 = 24576000 Hz UCSCTL2 = FLLD__2 | 374; // 允许 FLL 控制 __bic_SR_register(SCG0); __delay_cycles(384000); do { UCSCTL7 &= ~(DCOFFG); __delay_cycles(30); } while (UCSCTL7 & DCOFFG); // ACLK=XT1CLK SMCLK=DCOCLK MCLK=DCOCLK UCSCTL4 = SELA__XT1CLK SELS__DCOCLK SELM__DCOCLK; //---------------------------------------------------------- // P2功能【外接信号】 功能 方向 初始值 // P2.1 | PM_UCB0SIMO |【PM_UCB0SDA】| COM7 1[I/O] 1[O] [1] // P2.0 | PM_UCB0SOMI |【PM_UCB0SCL】| COM6 1[I/O] 1[O] [1] //---------------------------------------------------------- P2SEL = 0x03; P2DIR = 0xff; P2OUT = 0xff; P2MAP1 = PM_UCB0SDA; // P2.1【PM_UCB0SDA】-> I2C_SDA P2MAP0 = PM_UCB0SCL; // P2.0【PM_UCB0SCL】-> I2C_SCL P2REN |= 0x03; //--------------------------------- // USCI(UCB0)初始化: 用于I2C //--------------------------------- // USCI(UCB0)->复位状态 UCB0CTLW0 |= UCSWRST; // I2C模式的Master mode 7bit地址模式 单主设备模式 // 时钟 = SMCLK = 24576000 Hz UCB0CTLW0 = 0x0F81; // BPS = 24576000 / 256 = 96000 Hz UCB0BRW = 256; } // BPS=96000 传输一个BYTE时间 = 8/96000 = 83us 延时122us可以保证传输时间足够 #define DELAY_I2C (__delay_cycles(3000)) // 122us = 122 / (1/24.576) = 2998 //--------------------------------- // 写EEPROM(24CL04) //--------------------------------- void WriteEE(uint EEAddr uchar *RamAddr uint Len) { uint i ui_cmd; if (Len == 0) return; // USCI(UCB0)->复位状态 UCB0CTLW0 |= UCSWRST; // Transmitter 模式 UCB0CTLW0 |= UCTR; // 发送START UCB0CTLW0 |= UCTXSTT; // SEND SLAVE ADDRESS ui_cmd = EEAddr >> 8; ui_cmd &= 0x0001; ui_cmd = 0x0050; UCB0I2CSA = ui_cmd; // USCI(UCB0)->工作状态 UCB0CTLW0 &= ~UCSWRST; DELAY_I2C; // SEND WORD ADDRESS UCB0TXBUF = EEAddr & 0x00ff; DELAY_I2C; for (i=0; i<Len; i ) { UCB0TXBUF = RamAddr[i]; DELAY_I2C; } // 发送STOP UCB0CTLW0 |= UCTXSTP; DELAY_I2C; } //--------------------------------- // 读EEPROM(24CL04) //--------------------------------- void ReadEE(uint EEAddr uchar *RamAddr uint Len) { uint i ui_cmd; if (Len == 0) return; // USCI(UCB0)->复位状态 UCB0CTLW0 |= UCSWRST; // Transmitter 模式 UCB0CTLW0 |= UCTR; // 发送START UCB0CTLW0 |= UCTXSTT; // SEND SLAVE ADDRESS ui_cmd = EEAddr >> 8; ui_cmd &= 0x0001; ui_cmd = 0x0050; UCB0I2CSA = ui_cmd; // USCI(UCB0)->工作状态 UCB0CTLW0 &= ~UCSWRST; DELAY_I2C; // SEND WORD ADDRESS UCB0TXBUF = EEAddr & 0x00ff; DELAY_I2C; // 发送STOP UCB0CTLW0 |= UCTXSTP; DELAY_I2C; // USCI(UCB0)->复位状态 UCB0CTLW0 |= UCSWRST; // Receiver 模式 UCB0CTLW0 &= ~UCTR; // 发送START UCB0CTLW0 |= UCTXSTT; // SEND SLAVE ADDRESS ui_cmd = EEAddr >> 8; ui_cmd &= 0x0001; ui_cmd = 0x0050; UCB0I2CSA = ui_cmd; // USCI(UCB0)->工作状态 UCB0CTLW0 &= ~UCSWRST; DELAY_I2C; for (i=0; i<Len; i ) { DELAY_I2C; if (i == (Len-1)) { // 发送STOP UCB0CTLW0 |= UCTXSTP; } RamAddr[i] = (uchar)UCB0RXBUF; } // 发送STOP UCB0CTLW0 |= UCTXSTP; DELAY_I2C; } //--------------------------------- // 主流程 //--------------------------------- void main(void) { uchar i sbuf[10]; // 初始化MCU Mcu_Init(); // 初始化LCD Lcd_Init(); Disp_RomString(Msg_UCB0_I2C LINE1 NORMAL); Disp_RomString(Msg_WriteEE LINE4 NORMAL); Disp_RomString(Msg_ReadEE LINE7 NORMAL); i = 0; while(1) { sbuf[0] = i 0x30; sbuf[1] = i 0x31; sbuf[2] = i 0x32; sbuf[3] = i 0x33; sbuf[4] = 0; WriteEE(10 sbuf 4); Disp_RamString8x16(sbuf LINE4 11 NORMAL); DELAY_400ms; memset(sbuf 0 sizeof(sbuf)); ReadEE(10 sbuf 4); Disp_RamString8x16(sbuf LINE7 11 NORMAL); DELAY_400ms; i = (i 1) % 7; } }

视频演示内容:先向EEPROM的地址0写入字符串,然后从此地址读出,看是否与写入的内容一致

猜您喜欢: