嵌入式式系统作业
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录
摘要 (1)
第一章绪论 (2)
第二章相关芯片介绍 (3)
2.1 TMS320F28335 (3)
2.2 加速度传感器ADXL345 (4)
2.3 角速度传感器L3G4200 (5)
第三章DSP的I2C通讯原理 (6)
3.1 ADXL345的I2C接口 (6)
3.2 L3G4200的I2C接口 (8)
3.3 TMS320F28335的I2C接口 (9)
第四章工作电路设计 (12)
4.1 电路设计 (12)
4.2 工作总结与展望 (14)
第五章致谢 (15)
附录 (16)
摘要
经过一个学期的学习,对嵌入式系统从感性认识上升到了理性的认识,同时在毕老师耐心细致的讲解下,对嵌入式系统的开发与编程有了更深的了解。
恰逢此时课题组的无人机姿态测量要开发一块控制板,结合课堂所学知识,立足于课题组的要求,设计并开发了这款F28335系列的DSP,经过调试与实验,结果令人满意。
本文涉及到的电路和程序主要用于一款小型无人直升机控制系统。
应用TI 公司的新型32位DSP TMS320F28335采集三轴加速度计ADXL345及三轴角速度传感器L3G4200的姿态数据,并将该数据用于无人直升机的姿态控制中,主要控制策略如下所述:首先,由三轴加速度计ADXL345及三轴角速度传感器L3G4200组成的六轴姿态测量模块测得直升机在X、Y、Z三轴上的加速度以及绕着这三轴的角速度,这些姿态信息通过一条I2C总线上传给DSPF28335进行采集,在DSP 中,飞控算法将这些姿态信息与输入的预期姿态值进行比较,应用经典PID控制算法进行姿态控制和调整,调整的结果是使得DSP输出占空比可调的PWM信号,该信号控制无人直升机主旋翼电机转速,主旋翼电机的转速与PWM信号的占空比成正相关,同时,主旋翼电机的转速不同,产生的升力不同,直升机的姿态也会随着升力变化而相应变化(具体的变化规律可参考有关直升机数学建模文献),因此,通过控制DSP输出的PWM信号的占空比,就可以达到控制无人直升机姿态的目的。
本文重点设计六轴姿态模块数据的采集部分,包括六轴姿态模块的电路设计以及信号采集程序设计
关键字:嵌入式;DSP;姿态传感器
第一章绪论
本文涉及到的电路和程序主要用于作者所设计的一款小型无人直升机控制系统,其作用是应用TI公司的新型32位DSP TMS320F28335采集三轴加速度计ADXL345及三轴角速度传感器L3G4200的姿态数据,并将该数据用于无人直升机的姿态控制中,主要控制策略如下所述:首先,由三轴加速度计ADXL345及三轴角速度传感器L3G4200组成的六轴姿态测量模块测得直升机在X、Y、Z三轴上的加速度以及绕着这三轴的角速度,这些姿态信息通过一条I2C总线上传给DSPF28335进行采集,在DSP中,飞控算法将这些姿态信息与输入的预期姿态值进行比较,应用经典PID控制算法进行姿态控制和调整,调整的结果是使得DSP 输出占空比可调的PWM斩波信号,该信号控制无人直升机主旋翼电机转速,主旋翼电机的转速与PWM斩波信号的占空比成正相关,同时,主旋翼电机的转速不同,产生的升力不同,直升机的姿态也会随着升力变化而相应变化(具体的变化规律可参考有关直升机数学建模文献),因此,通过控制DSP输出的斩波信号的占空比,就可以达到控制无人直升机姿态的目的。
本文重点设计六轴姿态模块数据的采集部分,包括六轴姿态模块的电路设计以及信号采集程序设计。
第二章相关芯片介绍
设计中主要用到的芯片包括三种:TI公司的TMS320F28335系列DSP,AD公司的三轴加速度计ADXL345,ST公司的三轴角速度传感器L3G4200。
下面对这三种主要芯片做简要介绍。
2.1 TMS320F28335
TMS320F28335是TI公司生产的一款最新DSP,该DSP为32-位浮点型,主频率为150MHz,作者使用的是由南京研旭公司生产的F28335的核心板,该核心板主要配置包括:
①片上存储器:
FLASH:256K×16-位
SRAM:34K×16-位
Boot ROM:8K×16-位
OTP ROM:1K×16-位
其中FLASH、OTP ROM 和16K×16-位SRAM 受密码保护,保护用户程序。
②片上外设:
ePWM:12 路
HRPWM:6 路
QEP:2 通道
ADC:2×8 通道、12-位、80ns 转换时间、0~3V 量程
SCI 异步串口:3 通道
McBSP 同步串口:2 通道
SPI 同步串口:1 通道
eCAN 总线:2 通道
I2C 总线:1 通道
DMA:6 通道
看门狗
外扩SRAM,最大容量为512K x 16 位,基本配置为64K x 16 位
外扩RTC 实时时钟+ 512×8-位EEPROM
外扩4 通道、12-位分辩率、10μs 建立时间、±10V 量程的DAC 输出
…外扩符合USB2.0 标准的高速客户端接口
2路SCI 进行收发驱动,接口标准一路为RS232,另一路RS232/RS422
/RS485可配置
1路eCAN进行收发驱动,符合CAN2.0 协议
标准的JTAG接口,方便调试,标准化的扩展总线。
本设计中主要用到的是该开发板中的I2C总线,实现DSP与两个传感器之间的通讯。
2.2 加速度传感器ADXL345
ADXL345是一款小而薄的超低功耗3轴加速度计,分辨率高(13位),测量范围达±16g。
数字输出数据为16位二进制补码格式,可通过SPI(3线或4线)或I2C数字接口访问。
其主要电气特性包括:
超低功耗:VS = 2.5 V时(典型值),测量模式下低至23A,待机模式下为0.1μA
功耗随带宽自动按比例变化
用户可选的分辨率
10位固定分辨率
全分辨率,分辨率随g范围提高而提高,±16g时高达13位
(在所有g范围内保持4 mg/LSB的比例系数)
电源电压范围:2.0 V至3.6 V
I / O电压范围:1.7 V至VS
SPI(3线和4线)和I2C数字接口
灵活的中断模式,可映射到任一中断引脚
通过串行命令可选测量范围
通过串行命令可选带宽
宽温度范围(-40°C至+85℃)
抗冲击能力:10,000 g
本设计中主要通过I2C总线将ADXL345与DSPF28335连接。
2.3 角速度传感器L3G4200
L3G4200是由ST公司生产的一种三轴角速度传感器,它包括一个感应单元和一个IC接口单元,该接口单元提供3线SPI及I2C通讯接口。
其主要电气特性包括:
三种可选满量程(250/500/2000°/s),
I2C/SPI数据接口。
16位角速度数据输出。
8位温度值输出。
可选的内部集成高通/低通滤波器。
内嵌的温度传感器。
支持2.4v至3.6v供电电压。
工作温度-45至80度。
第三章DSP的I2C通讯原理
3.1 ADXL345的I2C接口
ADXL345的的主要功能模块包括一个三轴硅晶体传感器,一个AD转换模块,一组数字滤波器,一个32位的FIFO缓存模块以及串口通讯模块和电源管理模块。
以下是ADXL345的主要功能模块框图。
图一ADXL345主要功能模块
如下图所示,CS引脚拉高至VDD I/O,ADXL345处于I2C模式,需要简单2线式连接。
ADXL345符合《UM10204 I2C总线规范和用户手册》03版(2007年6月19日,NXP Semiconductors提供)。
如果满足了表11和表12列出的总线参数,便能支持标准(100 kHz)和快速(400 kHz)数据传输模式。
如图40所示,支持单个或多个字节的读取/写入。
ALT ADDRESS引脚处于高电平,器件的7位I2C 地址是0x1D,随后为R/W位。
这转化为0x3A写入,0x3B读取。
通过ALT ADDRESS 引脚(引脚12)接地,可以选择备用I2C地址0x53(随后为R/W位)。
这转化为0xA6写入,0xA7读取。
对于任何不使用的引脚,没有内部上拉或下拉电阻,因此,CS 引脚或ALT ADDRESS引脚悬空或不连接时,任何已知状态或默认状态不存在。
使用I2C时,CS引脚必须连接至VDD I/O,ALT ADDRESS引脚必须连接至任一VDD I/O或接地。
由于通信速度限制,使用400 kHz 的I2C最大输出数据速率为800 Hz,与I2C通信速度按比例呈线性变化。
例如,使用100 kHz I2C时,ODR最大
限值为200 Hz。
以高于推荐的最大值和最小值范围的输出数据速率运行,可能会对加速度数据产生不良影响,包括采样丢失或额外噪声。
如果有其他器件连接到同一I2C总线,这些器件的额定工作电压电平不能高于VDD I/O 0.3V以上。
I2C 正确操作需要外接上拉电阻RP。
L I/O
图二ADXL345I2C总线搭建
图二是ADXL345进行I2C通讯的时序图。
图三ADXL345I2C总线时序
图四I2C总线要求
上面的图三是ADXL345的I2C通讯各时序要求,与后面将要提到的DSPI2C 时序以及L3G4200的I2C时序相比较可以看出,这三者的I2C均属于标准接口,因此可以方便的在三者之间搭起I2C总线。
3.2 L3G4200的I2C接口
L3G4200的内部主要模块包括一个AD转换模块,一个组滤波器,一个32
位的FIFO缓存以及一个SPI、I2C复用的接口,以下是L3G4200de各功能模块框图。
图五L3G4200功能模块框图
该I2C器件只可作为从器件,其地址根据SDO引脚的接地与否变化,SDO接
高电平时,该器件的7位I2C地址为1101001,当SDO接地时,该器件的7位I2C 地址为1101000。
L3G4200内嵌的I2C满足以下通讯协议:I2C总线上的主器件提供时钟脉冲序列,当L3G4200接收到主器件发送来START信号后,首相将自身地址与主器件发送的地址作比对,若相符,则L3G4200发送一个ACK信号以回应主器件,随后,L3G4200按照主器件发送的所要访问的访寄存器地址将该寄存器内数据发送到SDA引脚,供主器件查读。
主器件没读完一个寄存器地址,L3G4200自动将地址加1,做下一地址的数据读取。
SDA线上数据的高低电平跳变只能在时钟信号下降沿进行,在时钟信号为高时,SDA线上电平保持不变。
图四是L3G4200的I2C 总线时序要求。
图六L3G4200时序要求
3.3 TMS320F28335的I2C接口
TMS320F28335支持多主机的I2C总线通讯,该DSP既可以作为I2C主机使用,也可以作为从机使用。
在作为主机使用时,其I2C总线时钟频率有两个预分频的寄存器决定。
一个是IPSC,另一个是ICCL和ICCH。
TMS320F28335的I2C模块主要包括控制寄存器,数据寄存器,一个32位的FIFO缓存,主频预分频模块这几个部分,以下是其各功能模块的框图。
IPSC是对I2C模块的输入时钟(亦即DSP的主频)进行第一次分频,该分频的结果既是I2C模块的频率,一般情况下,同时考虑通讯速率以及通讯准确率,要求I2C模块频率应该介于7至15MHz之间。
I2C模块时钟频率与IPSC以及DSP 主频率之间的关系可以由下式说明:
Module Clock Frequency = I2C Input Clock Frequency / (IPSC+1) 在本设计中,取IPSC为9,这样,I2C模块的时钟频率为10MHz(TMS320F28335的主频率为150MHz)。
ICCL与ICCH是对I2C模块式中再进行一次分频,这次分频确定的是I2C通讯时输出的时钟上升沿和下降沿的持续时间。
时钟高电平的持续时间由ICCH决定,低电平持续时间由ICCL决定。
高、低电平持续时间与ICCH、ICCL之间的关系由下式决定:
Ht=Module Period*(ICCH + d);
Lt= Module Period*(ICCL + d);
其中,d的取值由IPSC确定,当IPSC>1时,d=5。
同时,F28335的I2C不仅支持1—8位的数据格式,还支持自由数据格式,这样,就方便了DSP与各类不同标准数据结构器件之间的通讯。
下图是F28335与其他I2C器件搭建I2C总线的图示。
图七DSP28335与其他I2C之间搭建总线
第四章工作电路设计
4.1 电路设计
由于ADXL345、L3G4200要与DSP进行I/O口电压匹配,因此,需要设计专门的外围电路,在本设计中,作者将ADXL345和L3G4200集成在一块板子上,外围电路一起设计,以下是这两者集成的电路各部分原理图。
图八电源部分原理图
图九ADXL345外围电路原理图
图十L3G4200外围电路
图十一引出管脚设置
图十二六轴模块全局电路原理图
图十中,引出管脚J1的1号引脚是整个模块的供电脚,上接3.3v电源,2号引脚是电源地,3号引脚为I2C通讯的时钟管脚,接F28335的I2C模块的SCL,4号引脚为I2C的数据引脚,接F28335的对应引脚。
5号引脚悬空。
J2管脚的1号引脚接电源,2号引脚为SPI通讯的数据输出脚,3号引脚为SPI通讯的数据输
入脚,4号管脚是SPI通讯时的片选信号引脚,5号引脚为外部中断引脚,在设计中未用到。
实际应用中,将六轴模块的I2C相应引脚与DSP28335的相应I2C引脚连接,以DSP28335作为主机,以六轴模块作为从机,由DSP28335发送通讯同步时钟,对六轴模块作读写操作。
需要特别说明的是,ADXL345和L3G4200这两个传感器在I2C总线中的地址是可以由地址线的接地与否改变的。
具体为:ADX345的SDO/ALT ADDRESS引脚接地,I2C地址0x53(随后为R/W位)。
这转化为0xA6写入,0xA7读取。
读为高,写为低。
L3G4200的SDO接高电平,IIC地址为address 1101001b (0x69,随后为R/W位)。
这转化为0xD2写入,0xD3读取。
读为高,写为低。
在设计中,为了方便编程,同时简化电路,作者将ADXL345和L3G4200的地址引脚都设置为接地,因此,程序中对ADXL345的访问地址为0x53,对L3G4200的访问为0x69。
附录里给出了DSP与六轴模块之间通讯的主要程序端,这里对主要程序端做以下简要说明。
第一步,先对DSP进行系统初始化,然后设定第33和34号引脚为I2C的I/O 口(具体地说,33引脚对应SCLK同步时钟线,34引脚对应SDA数据线)。
第二步,对F28335的I2C模块进行设置,主要包括模块时钟频率设置,中断设置,主(从)器件设置,数据格式设置,FIFO设置等。
第三步,DSP通过I2C总线向六轴模块发送指令,既向六轴模块相应寄存器写入控制字。
第四步,DSP作为主器件,六轴模块的两个传感器ADXL345和L3G4200作为从器件,由DSP启动I2C通讯,读取六轴模块的数据。
4.2 工作总结与展望
经过一系列调试与实验,目前本设计中提到的I2C总线已经成功应用到无人直升机的姿态数据采集上,采集效果良好,电路工作稳定,程序运行可靠,下一步我们将考虑把DSP芯片和ADXL345以及L3G4200集成到一块板子上,开发出无人直升机专用的,集姿态测量、姿态控制为一体的控制卡。
为研究者们提供专门封装好的惯性测量、数据处理与控制于一体的控制电路板,实现高度集成。
第五章致谢
毕宏彦老师是我在嵌入式电路设计与开发方面的启蒙老师,我如今在嵌入式开发领域所获得的没一点滴知识源自于毕老师的辛勤汗水。
所以在这里我要感谢毕宏彦老师耐心细致的讲授、孜孜不倦的教诲。
毕老师所传授给我们的不仅仅是关于嵌入式电路设计的相关知识,他老人家更传授给我们一种严谨认真的求学态度以及踏实负责的为人处事之原则。
这将是我们受用一生的宝贵财富。
在这里祝福他老人家:
桃李芬芳做栋梁,享誉业界体健康!
附录
以下是由DSP采集六轴模块的数据,主要程序语句如下
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h" // DSP2833x Examples Include File
void I2CA_Init(void);
Uint16 I2CA_WriteData(struct I2CMSG *msg);
Uint16 I2CA_ReadData(struct I2CMSG *msg);
void WriteData(struct I2CMSG *msg,Uint16 *MsgBuffer,Uint16 MemoryAdd,Uint16 NumOfBytes);
interrupt void i2c_int1a_isr(void);
void pass(void);
void fail(void);
#define I2C_SLAVE_ADDR 0x53
#define I2C_NUMBYTES 1
#define I2C_RNUMBYTES 6
#define I2C_L3G345_X_HIGH_ADDR 0x33
#define I2C_L3G345_X_LOW_ADDR 0x32
int X;
int Y;
int Z;
float x;
float y;
float z;
struct I2CMSG I2cMsgOut1={I2C_MSGSTAT_SEND_WITHSTOP,
I2C_SLAVE_ADDR,
I2C_NUMBYTES,
I2C_L3G345_X_HIGH_ADDR,
I2C_L3G345_X_LOW_ADDR};
struct I2CMSG I2cMsgIn1={ I2C_MSGSTAT_SEND_NOSTOP,
I2C_SLAVE_ADDR,
I2C_RNUMBYTES,
I2C_L3G345_X_HIGH_ADDR,
I2C_L3G345_X_LOW_ADDR};
struct I2CMSG *CurrentMsgPtr; // Used in interrupts Uint16 PassCount;
Uint16 FailCount;
void main(void)
{
Uint16 i;
CurrentMsgPtr = &I2cMsgOut1;
InitSysCtrl();
InitI2CGpio();
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EALLOW;
PieVectTable.I2CINT1A = &i2c_int1a_isr;
EDIS;
I2CA_Init();
PieCtrlRegs.PIEIER8.bit.INTx1 = 1;
IER |= M_INT8;
EINT;//write data
if(I2cMsgOut1.MsgStatus == I2C_MSGSTAT_SEND_WITHSTOP)
{
i = 0x0B;
WriteData(&I2cMsgOut1,&i,0x31,1);
DELAY_US(1000);
WriteData(&I2cMsgOut1,&i,0x2C,1);
DELAY_US(1000);
i = 0x08;
WriteData(&I2cMsgOut1,&i,0x2D,1);
DELAY_US(1000);
i = 0x80;
WriteData(&I2cMsgOut1,&i,0x2E,1);
DELAY_US(1000);
i = 0x00;
WriteData(&I2cMsgOut1,&i,0x1E,1);
DELAY_US(1000);
i = 0x00;
WriteData(&I2cMsgOut1,&i,0x1F,1);
DELAY_US(1000);
i = 0x05;
WriteData(&I2cMsgOut1,&i,0x20,1);
DELAY_US(1000);//read data
for(;;)
{
// Check outgoing message status. Bypass read section if status is // not inactive.
if (I2cMsgOut1.MsgStatus == I2C_MSGSTAT_INACTIVE)
{
if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP)
{
while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS)
{
t++;
if (t>=15)
brake;
}
}
// Update current message pointer and message status
CurrentMsgPtr = &I2cMsgIn1;
I2cMsgIn1.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY; }
else if(I2cMsgIn1.MsgStatus == I2C_MSGSTAT_RESTART)
{
DELAY_US(1000000);
X = (I2cMsgIn1.MsgBuffer[5] << 8) + I2cMsgIn1.MsgBuffer[4];
Y = (I2cMsgIn1.MsgBuffer[3] << 8) + I2cMsgIn1.MsgBuffer[2];
Z = (I2cMsgIn1.MsgBuffer[1] << 8) + I2cMsgIn1.MsgBuffer[0]; if(X<0)
{
X=-X;
}
else
{
X=X;
}
x=(float)X*3.9; //x轴加速度,单位mg
if(Y<0)
{
Y=-Y;
}
else
{
Y=Y;
}
y=(float)Y*3.9; //y轴加速度,单位mg
if(Z<0)
{
Z=-Z;
}
else
{
Z=Z;
}
z=(float)Z*3.9; //z轴加速度,单位mg
// Read data portion
while(I2CA_ReadData(&I2cMsgIn1) != I2C_SUCCESS)
{
f++;
if(f>=7)
brake;
}
// Update current message pointer and message status CurrentMsgPtr = &I2cMsgIn1;
I2cMsgIn1.MsgStatus = I2C_MSGSTAT_READ_BUSY;
//Update new data
X = (I2cMsgIn1.MsgBuffer[5] << 8) + I2cMsgIn1.MsgBuffer[4]; Y = (I2cMsgIn1.MsgBuffer[3] << 8) + I2cMsgIn1.MsgBuffer[2]; Z = (I2cMsgIn1.MsgBuffer[1] << 8) + I2cMsgIn1.MsgBuffer[0]; if(X<0)
{
X=-X;
}
else
{
X=X;
}
x=(float)X*3.9; //x轴加速度,单位mg
if(Y<0)
{
Y=-Y;
}
else
{
Y=Y;
}
y=(float)Y*3.9; //y轴加速度,单位mg
if(Z<0)
{
Z=-Z;
}
else
{
Z=Z;
}
z=(float)Z*3.9; //z轴加速度,单位mg
}
} // end of read section
} // end of for(;;)
} // end of main
// Initialize I2C
Uint16 I2CA_WriteData(struct I2CMSG *msg)
{
Uint16 i;
if (I2caRegs.I2CMDR.bit.STP == 1)
{
return I2C_STP_NOT_READY_ERROR;
}
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<msg->NumOfBytes-2; i++)
for (i=0; i<msg->NumOfBytes; i++)
{
I2caRegs.I2CDXR = *(msg->MsgBuffer+i);
}
// Send start as master transmitter
I2caRegs.I2CMDR.all = 0x6E20;
return I2C_SUCCESS;
}
Uint16 I2CA_ReadData(struct I2CMSG *msg)
{
// 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)
{
// Check if bus busy
if (I2caRegs.I2CSTR.bit.BB == 1)
{
return I2C_BUS_BUSY_ERROR;
}
I2caRegs.I2CCNT = 2;
I2caRegs.I2CDXR = msg->MemoryHighAddr;
I2caRegs.I2CDXR = msg->MemoryLowAddr;
I2caRegs.I2CMDR.all = 0x2620; // Send data to setup RTC address }
else if(msg->MsgStatus == I2C_MSGSTAT_RESTART)
{
I2caRegs.I2CCNT = msg->NumOfBytes; // Setup how many bytes to expect I2caRegs.I2CMDR.all = 0x2C20; // Send restart as master receiver }
t=300;
Return I2C_SUCCESS;
}
interrupt void i2c_int1a_isr(void) // I2C-A
{
Uint16 IntSource, i;
// Read interrupt source
IntSource = I2caRegs.I2CISRC.all;
// Interrupt source = stop condition detected
if(IntSource == I2C_SCD_ISRC)
{
// 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(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
{
CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;
}
// If completed message was reading RTC data, reset msg to inactive state
// and read data from FIFO.
else if (CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_READ_BUSY)
{
CurrentMsgPtr->MsgStatus =
I2C_MSGSTAT_SEND_NOSTOP;//I2C_MSGSTAT_INACTIVE;
for(i=0; i < CurrentMsgPtr->NumOfBytes; i++)
{
CurrentMsgPtr->MsgBuffer[i] = I2caRegs.I2CDRR;
}
}
}
} // end of stop condition detected
// Interrupt source = Register Access Ready
.
else if(IntSource == I2C_ARDY_ISRC)
{
if(I2caRegs.I2CSTR.bit.NACK == 1)
{
I2caRegs.I2CMDR.bit.STP = 1;
I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
}
else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
{
CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART;
}
t=200;
} // 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 WriteData(struct I2CMSG *msg,Uint16 *MsgBuffer,Uint16 MemoryAdd,Uint16
NumOfBytes)
{
Uint16 i,Error;
for(i = 0; i < NumOfBytes; i++)
{
msg->MsgBuffer[i] = MsgBuffer[i];
}
msg->MemoryHighAddr = MemoryAdd >> 8;
msg->MemoryLowAddr = MemoryAdd & 0xff;
msg->NumOfBytes = NumOfBytes;
Error = I2CA_WriteData(&I2cMsgOut1);
if (Error == I2C_SUCCESS)
{
CurrentMsgPtr = &I2cMsgOut1;
I2cMsgOut1.MsgStatus = I2C_MSGSTAT_WRITE_BUSY;
xx=12;
}
while(I2cMsgOut1.MsgStatus != I2C_MSGSTAT_INACTIVE);
DELAY_US(1000);
}。