DSP2808中i2c实例分析
更新时间:2023-10-22 11:56:01 阅读量: 综合文库 文档下载
- dsp2808的介绍推荐度:
- 相关推荐
注意:本例分析基于DSP2808中的i2c_eeprom示例程序 和 AT24C1024 EEPROM存储器。当然,在学IIC之前要了解一下IIC工作流程,知道AT24C1024存储芯片的使用方法。 现在按以下4部分来介绍这个示例。
1.示例程序中几种状态说明
第一次看i2c_eeprom示例程序,对程序中的MsgStatus信息状态切换非常懵懂,为什么要有这几个状态?状态切换顺序如何安排?一大堆的状态,让人有些摸不着头脑。先把程序中的头文件
涉及的7种状态分析一下。
// I2C Message Commands for I2CMSG struct
#define I2C_MSGSTAT_INACTIVE 0x0000 //未激活状态:一般成功发送数据或者//接受数据后可以设置信息状态为此状态,告诉用户可进行下一次的写数据或读数据。 #define I2C_MSGSTAT_SEND_WITHSTOP 0x0010 //发送带停止位数据:这是为写数据而设///的状态,写入地址和数据之后发个停止位告诉存储器数据写入完毕。
#define I2C_MSGSTAT_WRITE_BUSY 0x0011 //写数据忙状态:在将待写的数据放入//缓存后,就可以使能IIC传输数据了,然后把信息状态设为该状态,意在告诉用户:数据//已经在传送过程中。当然是否传送完毕,还需要通过查询SCD位来判断。
#define I2C_MSGSTAT_SEND_NOSTOP 0x0020//发送无停止位数据:这个状态是为了读//取数据而设的,有查阅过AT24C1024EEPROM存储器使用手册的读者知道,在读数据之前//要发送数据的地址,发完地址不能产生停止位,这是存储器硬件设计决定的。设为这个状//态意在告诉读者,可以发送要读取的数据的地址了。
#define I2C_MSGSTAT_SEND_NOSTOP_BUSY 0x0021//发送无停止位数据忙状态:这个状态是//为了读取数据而设的,似于I2C_MSGSTAT_WRITE_BUSY,说明地址数据已经在传送过程中。//传送是否成功,还要看ARDY的状态。
#define I2C_MSGSTAT_RESTART 0x0022//重发开始位状态:这个状态也是为读取 ////数据而设。我们知道,读取存储器数据主要分两个步骤:第一,发送START位+设备地址 //+数据地址+无停止位。第二,再发START位+设备地址,紧接着存储器发送数据到IIC接收 //缓存器(I2CDRR),接收到设定好的数据数量(I2CCNT值)时输出停止位STOP.
//值得注意的是:理论上写完数据就能马上读取 数据 ,但事实上EEPROM存储器仍需要一 ////定延时来存储数据,约有2ms左右。通过示波器可以观察到,写完数据后,并不能马上 //成功读取数据,也就是说读数据的第一步骤要重复好几次(总线为50K时,大约要重复 //8次)才能成功。
#define I2C_MSGSTAT_READ_BUSY 0x0023//读取数据忙状态:这个状态是为读取数 //据而设。在读数据的第二步骤中,发完START位+设备地址后,就设为这一状态。意在说//明IIC开始等待接收固定数量(I2CCNT值)的数据。可以通过查询ARDY位判断。
//头文件中的其他定义应该没什么大问题了!
2. AT24C1024 EEPROM读写数据格式
(1)AT24C1024设备地址: 1 0 1 0 0 A1 P0 R/W
(2)单字节写入:START -> 发送从设备地址(写控制码R/W=0) -> 处理Ack -> 发送字节地址 -> 处理Ack [-> 发送1字节数据 -> 处理Ack] -> STOP。如下图:
(3)按页写入: START -> 发送从设备地址(写控制码R/W=0) -> 处理Ack -> 发送字节地址 -> 处理Ack [-> 发送1字节数据 -> 处理Ack-> 发送第2字节数据 -> 处理Ack-> 发送第3字节数据 -> 处理Ack……直到发完X字节] -> STOP。如下图。注意,连续写入的数据字节数不能超过每页所能容下的总量。如果写入的数据超过一页的长度,将发生回卷,即从EEPROM的0地址处进行数据覆盖。比如,AT24C1024有512页,每页最大容纳256字节。超过这个长度,地址指针将从每页首地址重新开始。
(4)随机单字节读取:第一步:发START -> 发送从设备地址(写控制码R/W=0) -> 处理Ack -> 发送字节地址高位 -> 处理Ack -> 发送字节地址低位 -> 处理Ack -> 第二步:发START -> 发送器件地址(读控制码R/W=1) -> 处理Ack -> 接收1字节数据 -> STOP。
(5)随机连续读取:在随机单字节读取操作的STOP信号发送之前,加入若干个 [-> 发送Ack -> 接收1字节数据] 即可实现。
(6)当前位置单字节读取:START -> 发送从设备地址(读控制码) -> 处理Ack -> 发送字节地址 -> 处理Ack -> 接收1字节数据 -> STOP。当前指的是之前进行过读取操作但是没有发送STOP信号,EEPROM芯片内部指针所在的位置即为当前位置。
(7)当前位置连续读取:在当前位置单节读取操作的STOP信号发送之前,加入若干个 [-> 发送Ack -> 接收1字节数据] 即可实现。
备注:部分内容引用百度文库中的《I2C读写流程》文档
3. 主程序说明及流程图
详细的注释可以参见程序附录,,这里主要解释一下设备地址取0x50的缘由。从AT24C1024的数据手册可知,设备地址为
。而在程序
中设置的地址是0x50,即0B0101 0000。看似不妥,其实,这个例子中设备地址采用7位地址模式,这样只取0x50的低7位作为设备地址的高七位,设备地址的最低位R/W则由寄存器I2CMDR中的TRX位决定。这样读数据时设备地址为0B1010 0001,写数据时设备地址改为0B1010 0000。通过示波器可以验证这些数据。
问题1:每次检测到SCD中断时,也就是顺利发完指定数量的数据或者接收指定数量的数据了,理论上I2caRegs.I2CCNT==0,但是本人设了几个中断点去观察该寄存器的值,发现总是不为零。通过观察I2caRegs.I2CFFTX.bit.TXFFST和I2caRegs.I2CFFRX.bit.RXFFST,可以发现这两个寄存器为零时,I2caRegs.I2CCNT也不为零。由此可知,I2CCNT不能实时反映发送/接收存储器中数据的数量,不过可以用TXFFST/RXFFST来代替。
图1 主程序流程图,图2为写数据程序流程图,图3为读数据程序流程图,图4为中断函数流程图。
main主程序各模块初始化FOR循环I2cMsgOut1状态==I2C_MSGSTAT_SEND_WITHSTOP?Y调用I2CA_WriteData函数; 令ERR=该函数返回值NERR==I2C_SUCCESS?NYa.更改当前指针为:I2cMsgOut1b.令I2cMsgOut1状态=I2C_MSGSTAT_WRITE_BUSYI2cMsgOut1状态==I2C_MSGSTAT_INACTIVE?YI2cMsgIn1状态==I2C_MSGSTAT_SEND_NOSTOP?Y调用I2CA_ReadData函数; NN返回值==I2C_SUCCESS?YNa.更改当前指针为:I2cMsgIn1b.令I2cMsgOut1状态=I2C_MSGSTAT_SEND_NOSTOP_BUSYI2cMsgIn1状态== I2C_MSGSTAT_RESTART?Y调用I2CA_ReadData函数; NERR==I2C_SUCCESS?YNa.更改当前指针为:I2cMsgIn1b.令I2cMsgIn1状态=I2C_MSGSTAT_READ_BUSY
图1 主程序流程图
I2CA_ReadData函数NSTP==1?I2CA_WriteData函数NY返回:I2C_STP_NOT_READY_ERROR配置从设备地址STP==1?Y返回:I2C_STP_NOT_READY_ERROR配置从设备地址I2cMsgIn1状态==I2C_MSGSTAT_SEND_NOSTOP?YN总线忙否?(BB==1?)Y返回I2C_BUS_BUSY_ERRORN总线忙否?(BB==1?)Y返回I2C_BUS_BUSY_ERRORNI2cMsgIn1状态==I2C_MSGSTAT_RESTART?Y配置I2CCNTN配置I2CCNT;地址数据放入缓存;信息数据放入缓存;配置I2CMDR配置I2CCNT;地址数据放入缓存;配置I2CMDR配置I2CMDR返回I2C_SUCCESS返回I2C_SUCCESS
图2写数据程序流程图 图3读数据程序流程图
中断i2c_int1a_isr获取中断源:IntSource中断源==I2C_SCD_ISRC?YN当前状态==I2C_MSGSTAT_WRITE_BUSY?YNI2cMsgIn1当前状态==I2C_MSGSTAT_SEND_NOSTOP_BUSY?Y令I2cMsgIn1当前状态=I2C_MSGSTAT_SEND_NOSTOPI2cMsgIn1当前状态==I2C_MSGSTAT_READ_BUSY?Y令I2cMsgIn1当前状态=I2C_MSGSTAT_INACTIVE从接收缓存器I2CDRR读取数据数据处理:统计正确次数和错误次数N当前状态==I2C_MSGSTAT_SEND_NOSTOP_BUSY?Y令当前状态=I2C_MSGSTAT_RESTARTNNACK==1?Y设置IIC产生STOP位;清除NACK;N令I2cMsgOut1当前状态=I2C_MSGSTAT_INACTIVE中断源==I2C_ARDY_ISR?YN停止仿真NNPassCount==I2C_NUMBYTES?Y进入fail死循环进入Pass死循环中断返回
图4中断函数流程图
4.程序附录
//可以用以下代码替换示例程序Example_280xI2c_eeprom.c中的代码,再进行调试。//
//该程序跟原始程序没多大区别,主要改变为:引入几个统计变量,改变发送数据长度为2字节//
// TI File $Revision: /main/5 $
// Checkin $Date: April 4, 2007 17:18:36 $
//########################################################################### //
// FILE: Example_280xI2c_eeprom.c //
// TITLE: DSP280x I2C EEPROM Example //
// ASSUMPTIONS: //
// This program requires the DSP280x header files. //
// This program requires an external I2C EEPROM connected to // the I2C bus at address 0x50. //
// As supplied, this project is configured for \// operation. The 280x Boot Mode table is shown below. // For information on configuring the boot mode of an eZdsp, // please refer to the documentation included with the eZdsp, //
// Boot GPIO18 GPIO29 GPIO34 // Mode SPICLKA SCITXDA // SCITXB // -------------------------------------
// Flash 1 1 1 // SCI-A 1 1 0 // SPI-A 1 0 1 // I2C-A 1 0 0 // ECAN-A 0 1 1
// SARAM 0 1 0 <- \// OTP 0 0 1 // I/0 0 0 0 //
// DESCRIPTION: //
// This program will write 1-14 words to EEPROM and read them back. // The data written and the EEPROM address written to are contained // in the message structure, I2cMsgOut1. The data read back will be // contained in the message structure I2cMsgIn1.
// --------------------------------------------------------------
// CODE MODIFICATIONS ARE REQUIRED FOR 60 MHZ DEVICES (In // DSP280x_Examples.h in the common/include/ directory, set // #define CPU_FRQ_60MHZ to 1, and #define CPU_FRQ_100MHZ to 0). // --------------------------------------------------------------
// This program will work with the on-board I2C EEPROM supplied on // the F280x eZdsp. // //
//########################################################################### // Original Author: D.F. //
// $TI Release: DSP280x Header Files V1.60 $ // $Release Date: December 3, 2007 $
//###########################################################################
#include \ // DSP280x Headerfile Include File #include \ // DSP280x Examples Include File
// Note: I2C Macros used in this example can be found in the // DSP280x_I2C_defines.h file
// Prototype statements for functions found within this file. void I2CA_Init(void);
Uint16 I2CA_WriteData(struct I2CMSG *msg); Uint16 I2CA_ReadData(struct I2CMSG *msg); interrupt void i2c_int1a_isr(void); void pass(void); void fail(void);
#define I2C_SLAVE_ADDR 0x50 //EEPROM地址
#define I2C_NUMBYTES 2 //为方便示波器观察,设置发送2字节的数据 #define I2C_EEPROM_HIGH_ADDR 0x11 //数据的写入地址高位 #define I2C_EEPROM_LOW_ADDR 0x0F //数据的写入地址低位
// Global variables//全局变量
// Two bytes will be used for the outgoing address,//有2个字节是地址 // thus only setup 14 bytes maximum//最多只能设置14字节数据
struct I2CMSG I2cMsgOut1={I2C_MSGSTAT_SEND_WITHSTOP,//初始状态为:发送带停止位数据 I2C_SLAVE_ADDR, I2C_NUMBYTES,
I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR,
0xff, // Msg Byte 01 0x3F, // Msg Byte 02 0x56, // Msg Byte 03 0x78, // Msg Byte 04 0x9A, // Msg Byte 05 0xBC, // Msg Byte 06 0xDE, // Msg Byte 07 0xF0, // Msg Byte 08 0x11, // Msg Byte 09 0x10, // Msg Byte 10 0x11, // Msg Byte 11 0x12, // Msg Byte 12 0x13, // Msg Byte 13 0x12, };
struct I2CMSG I2cMsgIn1={ I2C_MSGSTAT_SEND_NOSTOP, I2C_SLAVE_ADDR, I2C_NUMBYTES,
I2C_EEPROM_HIGH_ADDR, I2C_EEPROM_LOW_ADDR};
struct I2CMSG *CurrentMsgPtr; Uint16 PassCount; Uint16 FailCount;
Uint16 ARDY_ISRC_NACK_number=0; //统计ARDY中断源引起的中断中NACK次数 Uint16 SCD_ISRC_number=0; //统计SCD中断源引起的中断次数 Uint16 ARDY_ISRC_number=0; //统计ARDY中断源引起的中断次数 Uint16 all_ISRC_number=0; //统计所有中断源引起的中断次数 Uint16 Write_load_num=0; //统计写数据函数调用次数
Uint16 Read_load_num1=0; //统计读数据函数调用次数1第一步骤 Uint16 Read_load_num2=0; //统计读数据函数调用次数2第二步骤
void main(void) {
Uint16 Error; Uint16 i;
CurrentMsgPtr = &I2cMsgOut1;
// Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP280x_SysCtrl.c file.
// Used in interrupts
// Msg Byte 14
InitSysCtrl();
// Step 2. Initalize GPIO:
// This example function is found in the DSP280x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // InitGpio();
// Setup only the GP I/O only for I2C functionality InitI2CGpio();
// Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT;
// Initialize PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared.
// This function is found in the DSP280x_PieCtrl.c file. InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR).
// This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in DSP280x_DefaultIsr.c. // This function is found in DSP280x_PieVect.c. InitPieVectTable();
// Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW;
// This is needed to write to EALLOW protected registers
PieVectTable.I2CINT1A = &i2c_int1a_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 4. Initialize all the Device Peripherals: // This function is found in DSP280x_InitPeripherals.c // InitPeripherals(); // Not required for this example I2CA_Init();
// Step 5. User specific code
// Clear Counters PassCount = 0; FailCount = 0;
// Clear incoming message buffer for (i = 0; i < I2C_MAX_BUFFER_SIZE; i++) {
I2cMsgIn1.MsgBuffer[i] = 0x0000; }
// Enable interrupts required for this example
// Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1 PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
// Enable CPU INT8 which is connected to PIE group 8 IER |= M_INT8; EINT;
// Application loop for(;;) {
////////////////////////////////// // Write data to EEPROM section // //////////////////////////////////
// Check the outgoing message to see if it should be sent. // In this example it is initialized to send with a stop bit. if(I2cMsgOut1.MsgStatus == I2C_MSGSTAT_SEND_WITHSTOP) { Write_load_num++;
Error = I2CA_WriteData(&I2cMsgOut1);
// If communication is correctly initiated, set msg status to busy//如果通信已经正确初始化,设置msg状态为’忙‘,并 // and update CurrentMsgPtr for the interrupt service routine. //更新作为中断服务路径的指针CurrentMsgPtr。
// Otherwise, do nothing and try again next loop. Once message is //否则,不做任何操作,等待下一次重新写数据。一旦信息正确 // initiated, the I2C interrupts will handle the rest. Search for //初始化,I2C中断将处理接下来的事情。可以在 // ICINTR1A_ISR in the i2c_eeprom_isr.c file. //i2c_eeprom_isr.c文件中找到ICINTR1A_ISR。 if (Error == I2C_SUCCESS) //数据已成功放入缓存寄存器 {
CurrentMsgPtr = &I2cMsgOut1; //改变指针路径 I2cMsgOut1.MsgStatus = I2C_MSGSTAT_WRITE_BUSY; //设为发送数据忙状态 }
} // end of write section
///////////////////////////////////
// Read data from EEPROM section //该过程包括两次发送START位,第一次发送地址 ///////////////////////////////////
// Check outgoing message status. Bypass read section if status is // not inactive.
if (I2cMsgOut1.MsgStatus == I2C_MSGSTAT_INACTIVE) {
// Check incoming message status.
if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP) { Read_load_num1++;
// EEPROM address setup portion
while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS) {
// Maybe setup an attempt counter to break an infinite while //这里可以设置一个计数器用于终止可能存在的无限循环。 // loop. The EEPROM will send back a NACK while it is performing//当EEPROM忙于处理写数据操作时,将返回一个NACK。 // a write operation. Even though the write communique is //对DSP来说,此刻写操作已经完成。但是,EEPROM仍需要 // complete at this point, the EEPROM could still be busy //一定时间完成数据的烧写1.8ms左右。在EEPROM完成烧写之前,都会 // programming the data. Therefore, multiple attempts are //返回NACK,告诉DSP它还在忙。因此,DSP需要多次尝试,直到 // necessary. //EEPROM空闲了,并返回ACK确认为止。 }
// Update current message pointer and message status CurrentMsgPtr = &I2cMsgIn1;
I2cMsgIn1.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY;
//第一次发送START成功,即地址数据已发送成功,给发无停止位数据忙状态,作为第二次发送START位标志 }
// Once message has progressed past setting up the internal address//一旦成功写入EEPROM地址,便可以再次发送START起始位 // of the EEPROM, send a restart to read the data bytes from the //然后从EEPROM存储器中读取数据。 // EEPROM. Complete the communique with a stop bit. MsgStatus is //DSP采可用一个停止位来结束数据接收。 // updated in the interrupt service routine. //msg状态在中断程序中被更新了。 else if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_RESTART) //该状态是在中断服务程序中态被赋予 { Read_load_num2++; // Read data portion
while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS) {
// Maybe setup an attempt counter to break an infinite while // loop. }
// Update current message pointer and message status CurrentMsgPtr = &I2cMsgIn1;
I2cMsgIn1.MsgStatus = I2C_MSGSTAT_READ_BUSY;
//第二次发送START,且数据接收成功,给下一个状态-读忙,作为中断中读取接收缓存中数据的标志 }
} // end of read section
} // end of for(;;) } // end of main
void I2CA_Init(void) {
// Initialize I2C
I2caRegs.I2CSAR = 0x0050;
#if (CPU_FRQ_100MHZ) I2caRegs.I2CPSC.all = 9; #endif
#if (CPU_FRQ_60MHZ) I2caRegs.I2CPSC.all = 6; #endif
I2caRegs.I2CCLKL = 95; I2caRegs.I2CCLKH = 95; I2caRegs.I2CIER.all = 0x24;
I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset
// Stop I2C when suspended
// NOTE: must be non zero // NOTE: must be non zero // Enable SCD & ARDY interrupts
// Prescaler - need 7-12 Mhz on module clk
// Prescaler - need 7-12 Mhz on module clk
// Slave address - EEPROM control code
//0b0000 0000 0010 0000,NACKMOD=0,FREE=0中断产生时IIC停止运行,STT=0不产生开始位,
//STP=0不产生停止位,MST=0从模式,TRX=0接收模式,XA=0 七位地址模式,RM=0不重复,DLB=0无回来 //IRS=1使能I2C模块,STB=0模块未处在开始字节模式,FDF=0自由数据格式被禁止 //注意:TRX决定AT24C1024设备地址中的R/W,这里R/W=1读数据 I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT,
return; }
Uint16 I2CA_WriteData(struct I2CMSG *msg) {
Uint16 i;
// Wait until the STP bit is cleared from any previous master communication. // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. if (I2caRegs.I2CMDR.bit.STP == 1) {
return I2C_STP_NOT_READY_ERROR; }
// Setup slave address
I2caRegs.I2CSAR = msg->SlaveAddress;
// Check if bus busy
if (I2caRegs.I2CSTR.bit.BB == 1) {
return I2C_BUS_BUSY_ERROR; }
////////判断总线空闲后进行数据发送//////// // Setup number of bytes to send // MsgBuffer + Address
I2caRegs.I2CCNT = msg->NumOfBytes+2; //递减
// Setup data to send
I2caRegs.I2CDXR = msg->MemoryHighAddr; I2caRegs.I2CDXR = msg->MemoryLowAddr; // for (i=0; i
I2caRegs.I2CDXR = *(msg->MsgBuffer+i); }
// Send start as master transmitter
I2caRegs.I2CMDR.all = 0x6E20; // 按以下参数配置IIC并使能IIC
//【0b0110 1110 0010 0000,NACKMOD=0,FREE=1中断产生时IIC能继续运行,STT=1产生开始位】
//【STP=1产生停止位,MST=1主模式,TRX=1发送,XA=0 七位地址模式,RM=0不重复,DLB=0无回路,IRS=1使能I2C模块,STB=0,FDF=0】 //开始发送数据,I2CCNT 递减模式统计数据到达0时产生中断,且产生停止位 //注意:TRX决定AT24C1024设备地址中的R/W,这里R/W=0写数据模式 return I2C_SUCCESS; }
Uint16 I2CA_ReadData(struct I2CMSG *msg)
{ //要完成一次读数据任务:要产生两个START位,产生第1个START位之后发送设备地址和数据地址; //产生第2个START位之后写入设备地址,并开始接收存储器提供的数据。 // Wait until the STP bit is cleared from any previous master communication. // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. if (I2caRegs.I2CMDR.bit.STP == 1)
{
return I2C_STP_NOT_READY_ERROR; }
I2caRegs.I2CSAR = msg->SlaveAddress;
if(msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP) //产生第一个START位之后发送设备地址和数据地址//// {
// Check if bus busy
if (I2caRegs.I2CSTR.bit.BB == 1) {
return I2C_BUS_BUSY_ERROR; }
I2caRegs.I2CCNT = 2; // 设置发送数据字节数-递减模式-等0时可以允许产生stop位(若使能STP) I2caRegs.I2CDXR = msg->MemoryHighAddr;//发送要读取数据的开始地址 I2caRegs.I2CDXR = (msg->MemoryLowAddr); I2caRegs.I2CMDR.all = 0x2620;
// 按以下参数配置IIC并使能IIC
//【STT =1发送起始位,STP=0不产生停止位,MST=1主模式,TRX=1发送,IRS=1使能I2C模块】
} // 开始发送数据I2CCNT 递减模式统计数据到达0时产生中断,但是没有产生停止位 //注意:TRX决定AT24C1024设备地址中的R/W,这里R/W=0写数据
else if(msg->MsgStatus == I2C_MSGSTAT_RESTART)//产生第2个START位之后发送设备地址,然后开始接收存储器提供的数据// {
I2caRegs.I2CCNT = msg->NumOfBytes; I2caRegs.I2CMDR.all = 0x2C20;
// 设置数据接收字节数量
// 按以下参数配置IIC并使能IIC
// 【STT =1发送起始位,STP=1产生停止位,MST=1主模式,TRX=0接收,IRS=1使能I2C模块】
} //开始接收数据,I2CCNT递减模式统计数据到达0时产生中断,有产生停止位 //注意-TRX决定AT24C1024设备地址中的R/W,这里R/W=1读数据
return I2C_SUCCESS; //到此说明发送地址/读取数据成功 }
interrupt void i2c_int1a_isr(void) // I2C-A {
Uint16 IntSource, i;
all_ISRC_number++;//统计所有中断次数 // Read interrupt source IntSource = I2caRegs.I2CISRC.all;
// Interrupt source = stop condition detected if(IntSource == I2C_SCD_ISRC) {
SCD_ISRC_number++;
// If completed message was writing data, reset msg to inactive state
if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_WRITE_BUSY) {
CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE;//发送完成,便换为未启动状态;说明可以进行下一次写数据 } else {
// If a message receives a NACK during the address setup portion of the // EEPROM read, the code further below included in the register access ready // interrupt source code will generate a stop condition. After the stop // condition is received (here), set the message status to try again. // User may want to limit the number of retries before generating an error.
if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)//发送无停止位地址忙 {
CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;//更新为发送停止位状态,可允许下一发送地址 }
// If completed message was reading EEPROM data, reset msg to inactive state // and read data from FIFO.
else if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_READ_BUSY) //读数据忙状态,说明可对接收缓存器I2CDRR进行接收数据读取了 {
CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_INACTIVE; //设为未启状态动,再读数据,这样允许下一次写数据到EEPROM for(i=0; i < I2C_NUMBYTES; i++) {
CurrentMsgPtr->MsgBuffer[i] = I2caRegs.I2CDRR; }
// Check recieved data //读完接收到的数据,接下来进行判断数据是否准确 for(i=0; i < I2C_NUMBYTES; i++) {
if(I2cMsgIn1.MsgBuffer[i] == I2cMsgOut1.MsgBuffer[i]) {
PassCount++; } else {
FailCount++; } }
if(PassCount == I2C_NUMBYTES) { pass(); } else { fail();
}
//检查完毕
} }
} // end of stop condition detected // Interrupt source = Register Access Ready
// This interrupt is used to determine when the EEPROM address setup portion of the //该中断用于判断读数据通讯中何时完成EEPROM数据地址的设置;
// read data communication is complete. Since no stop bit is commanded, this flag //由于不产生停止位,这个标志(ARDY)告诉我们地址数据是否发送完成。 // tells us when the message has been sent instead of the SCD flag. If a NACK is //如果收到NACK,清除NACK位,并设置产生一个停止位。
// received, clear the NACK bit and command a stop. Otherwise, move on to the read //否则,继续读取通讯数据。
// data portion of the communication. else if(IntSource == I2C_ARDY_ISRC) //IIC模块准备好中断:包括【复位,发完一个数据单元(1~8bits的数据)
{ //却没收到ACK/STOP或者出现counter=0】都可引发该中断 ARDY_ISRC_number++;
if(I2caRegs.I2CSTR.bit.NACK == 1) //因为EEPROM处理数据忙而回复的NACK {
I2caRegs.I2CMDR.bit.STP = 1; //产生一个STOP停止位,从而引发一次SCD中断。 I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT; //清除NACK位
ARDY_ISRC_NACK_number++;
}
else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY) {
CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART;//更新为重发START位状态,为接收数据准备 }
} // end of register access ready else {
// Generate some error due to invalid interrupt source asm(\ ESTOP0\ }
// Enable future I2C (PIE Group 8) interrupts
PieCtrlRegs.PIEACK.all = PIEACK_GROUP8; //重启中断允许 }
void pass()
{
asm(\ ESTOP0\ for(;;); } void fail() {
asm(\ ESTOP0\ for(;;); }
//=========================================================================== // No more.
//===========================================================================
正在阅读:
DSP2808中i2c实例分析10-22
世界气象日的由来03-14
可爱的家乡作文200字07-04
天纪-先天卦-后天卦-流年卦06-08
2008湘雅医学有机化学试题A07-25
令我后悔的一件事作文500字07-12
国际金融中英文版复习资料05-13
三年级下册数学教案第6单元长方形和正方形面积的计算 - 苏教版(04-24
《学会看病》教学反思优秀7篇03-23
一件印象深刻的事作文300字优秀作文04-05
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- 实例分析
- DSP2808
- i2c
- 边坡防护、挡墙、水沟安全技术交底
- 第11课导学案
- 关于国家发布《冷库设计规范》的标准1
- 2018届普陀区高考化学二模
- 2002年湖南大学材力试题
- 配件作业指导手册(终稿)
- 18 春江开 建设工程经济第四次作业 答案
- 冀教版四年级下册品德与社会复习题 - 图文
- 胶州市第二十六中学2012年第一届校园艺术节活动方案
- 浅谈纵向预应力混凝土技术开发与应用研究
- 尔雅社会心理学答案
- 《爬天都峰》说课稿
- 麻疹 试题(含答案)
- 法语词法
- 填空题、应用题
- 反思农村小学作文教学的困惑及其对策
- 2018解放思想大讨论活动心得体会(4篇)
- 入党申请书政治方面的表现
- 2012年最新医学正副高级职称(外科护理)考试题无忧-提炼真题模拟练习题及答案解析-过关必备
- 五年级下学期音乐教学计划