搞了两天,终于把LM3S6916的I2C功能搞定了:
与我以前用C51的I/O模拟做I2C的方法不同,它带有硬件的I2C接口,我以前没有用过硬件I2C接口,很久都没有明白怎么样读写,刚开始时以为这个接口不能做读写特殊的I2C设备,所以开始就没有好好研究这个硬件的I2C,先是想把C51下模拟做的I2C程序移值过来,结果在C51下能用的程序在这里改过之后会莫名的出错,也找不出问题出在哪里,现在把出错的程序贴上来,看有没有高手能帮我看看问题出在哪里。
void d10us(void)//20MHz lm3s6916
{
unsigned char ii;
for(ii=0;ii<0x43;ii++);
}
void d1ms(void)//20MHz lm3s6916
{
unsigned int ii;
for(ii=0;ii<0x1390;ii++);
}
void d5ms(void)//20MHz lm3s6916
{
unsigned int ii;
for(ii=0;ii<0x61d0;ii++);
}
void d5us(void)//20MHz lm3s6916
{
unsigned char ii;
for(ii=0;ii<0x14;ii++);
}
#define i2cSDA GPIO_PIN_3
#define i2cSCL GPIO_PIN_2
#define i2cGPIO_Port GPIO_PORTB_BASE
unsigned char bI2cError;
void SDA_H(void)
{
GPIOPinWrite(i2cGPIO_Port, i2cSDA,0xff);
GPIODirModeSet(i2cGPIO_Port, i2cSDA, GPIO_DIR_MODE_IN);
}
void SDA_L(void)
{
GPIODirModeSet(i2cGPIO_Port, i2cSDA, GPIO_DIR_MODE_OUT);
GPIOPinWrite(i2cGPIO_Port, i2cSDA,0x00);
}
void SCL_H(void)
{
GPIOPinWrite(i2cGPIO_Port, i2cSCL,0xff);
GPIODirModeSet(i2cGPIO_Port, i2cSCL, GPIO_DIR_MODE_IN);
}
void SCL_L(void)
{
GPIODirModeSet(i2cGPIO_Port, i2cSCL, GPIO_DIR_MODE_OUT);
GPIOPinWrite(i2cGPIO_Port, i2cSCL,0x00);
}
unsigned char SDA_S(void)
{
if(GPIOPinRead(i2cGPIO_Port, i2cSDA))return 1;
return 0;
}
unsigned char SCL_S(void)
{
if(GPIOPinRead(i2cGPIO_Port, i2cSCL))return 1;
return 0;
}
void IICInit(void)
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPadConfigSet(i2cGPIO_Port, i2cSCL|i2cSDA,GPIO_STRENGTH_8MA,GPIO_PIN_TYPE_OD);
GPIODirModeSet(i2cGPIO_Port, i2cSCL|i2cSDA, GPIO_DIR_MODE_OUT);
GPIOPinWrite(i2cGPIO_Port, i2cSCL|i2cSDA,0xff);
}
//*******************************************************************************************************
void IICStart(void)//启动总线
{
unsigned int ii;
dat=0;
ii=0;
bI2cError=0;
d5us();
//i2cSCL=1;
SCL_H();
d5us();
while(SCL_S()==0){
if(++ii==20000){//100ms
bI2cError=1;
return;
}
Hex2Str(ii>>8,&buf[0]);
Hex2Str(ii,&buf[2]);
lcd_display1(0, 0, 16, buf);
d5us();
}
//i2cSDA=1;
SDA_H();
d5us();
d5us();
d5us();
d5us();
//i2cSDA=0;
SDA_L();
d5us();
//i2cSCL=0;
SCL_L();
d5us();
//i2cSDA=1;
SDA_H();
d5us();
}
//*******************************************************************************************************
void IICStop(void)//停止IIC总线
{
d5us();
//i2cSDA=0;
SDA_L();
d5us();
//i2cSCL=1;
SCL_H();
d5us();
//i2cSDA=1;
SDA_H();
d5us();
//i2cSCL=0;
SCL_L();
d5us();
}
//*******************************************************************************************************
unsigned char IICRecAck(void)//检查应答位
{
unsigned int ii;
unsigned char k;
ii=0;
bI2cError=0;
d5us();
//i2cSDA=1;
SDA_H();
d5us();
//i2cSCL=1;
SCL_H();
d5us();
while(SCL_S()==0){
if(++ii==20000){//100ms
bI2cError=1;
return 0x01;
}
d5us();
}
k="SDA"_S();
d5us();
//i2cSCL=0;
SCL_L();
d5us();
return(k);
}
//*******************************************************************************************************
void IICAck(void)//对IIC总线产生应答
{
d5us();
//i2cSDA=0;
SDA_L();
d5us();
//i2cSCL=1;
SCL_H();
d5us();
//i2cSCL=0;
SCL_L();
d5us();
//i2cSDA=1;
SDA_H();
d5us();
}
//*******************************************************************************************************
void IICNoAck(void)//不对IIC总线产生应答
{
d5us();
//i2cSDA=1;
SDA_H();
d5us();
//i2cSCL=1;
SCL_H();
d5us();
//i2cSCL=0;
SCL_L();
d5us();
}
//*******************************************************************************************************
void IICSendByte(unsigned char sendbyte)//向IIC总线写数据
{
unsigned int ii;
unsigned char j="8";
ii=0;
bI2cError=0;
for(;j>0;j--){
if((sendbyte&0x80)!=0x00)SDA_H();
else SDA_L();
sendbyte<<=1;
d5us();
//i2cSCL=1;
SCL_H();
d5us();
while(SCL_S()==0){
if(++ii==20000){//100ms
bI2cError=1;
return;
}
d5us();
}
//i2cSCL=0;
SCL_L();
d5us();
}
}
//*******************************************************************************************************
unsigned char IICReceiveByte(void)//从IIC总线上读数据子程序
{
unsigned char ii;
unsigned char receivebyte;
unsigned char i;
receivebyte=0xaa;
ii=0;
d5us();
SDA_H();//
bI2cError=0;
d5us();
for(i=0;i<8;i++){
//i2cSCL=1;
SCL_H();
d5us();
while(SCL_S()==0){
if(++ii==20000){//100ms
bI2cError=1;
return 0xff;
}
d5us();
}
receivebyte=(receivebyte<<1)|SDA_S();
d5us();
//i2cSCL=0;
SCL_L();
d5us();
}
return(receivebyte);
}
unsigned char Read(unsigned char Addl)
{
unsigned char m;
d5ms();
IICStart();if(bI2cError)goto ReadErr;
IICSendByte(0xa0);if(bI2cError)goto ReadErr;
if(IICRecAck())goto ReadErr;
IICSendByte(Addl);if(bI2cError)goto ReadErr;
if(IICRecAck())goto ReadErr;
IICStart();if(bI2cError)goto ReadErr;
IICSendByte(0xa1);if(bI2cError)goto ReadErr;
if(IICRecAck())goto ReadErr;
m=IICReceiveByte();if(bI2cError)goto ReadErr;
IICNoAck();
IICStop();
return(m);
ReadErr:
IICStop();
return(0xf0);
}
/*--------------------------- main ------------------------------------------*/
int main (void) {
unsigned char i;
/* Set the clocking to run from the PLL at 20 MHz */
SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ);
for(i=0;i<250;i++)d1ms();
//-------------------------------------------------------
IICInit();
for(i=0;i<250;i++)d1ms();
i="Read"(0x06);//运行的结果是bI2cError=1,bI2cError=1表示过程出错了
while (1) {
}
}
以上是有错误的程序,目前没有解决问题,现象是出错后SDA脚变成了低电平,
把24C02的DAT脚断开后,LM3S6916的SDA脚也还是低电平,让人想不明白。
由于硬件I2C已经搞通了,所以以上模拟的程序就不再搞了,这个问题留给高手弄吧。
LM3S6916硬件I2C的程序以后择机会发上来的。
文章评论(0条评论)
登录后参与讨论