请教马老师IIC通讯程序问题
#include "I2C.h"/* 延时约5微秒,对于12M时钟 */
void delay5us()
{
uint i;
for (i=0;i<5;i++)
_nop_();
}
/* 起始条件子函数 */
void start(void)
{
SDA = 1; // 启动I2C总线
SCL = 1;
delay5us();
SDA = 0;
delay5us();
SCL = 0;
}
/* 停止条件子函数 */
void stop(void)
{
SDA = 0; // 停止I2C总线数据传送
SCL = 1;
delay5us();
SDA = 1;
delay5us();
SCL = 0;
}
/* 发送应答子函数 */
void ack(void)
{
SDA = 0; // 发送应答位
SCL = 1;
delay5us();
SDA = 1;
SCL = 0;
}
/* 发送非应答子函数 */
void n_ack(void)
{
SDA = 1; // 发送非应答位
SCL = 1;
delay5us();
SDA = 0;
SCL = 0;
}
/* 应答位检查子函数 */
void checkack(void)
{
SDA = 1; // 应答位检查(将p1.0设置成输入,必须先向端口写1)
SCL = 1;
nackFlag = 0;
if(SDA == 1) // 若SDA=1表明非应答,置位非应答标志F0
nackFlag = 1;
SCL = 0;
}
/* 发送一个字节数据子函数 */
void sendbyte(uchar idata *ch)
{
uchar idata n = 8;
uchar idata temp;
temp = *ch;
while(n--)
{
if((temp&0x80) == 0x80) // 若要发送的数据最高位为1则发送位1
{
SDA = 1; // 传送位1
SCL = 1;
delay5us();
SDA = 0;
SCL = 0;
}
else
{
SDA = 0; // 否则传送位0
SCL = 1;
delay5us();
SCL = 0;
}
temp = temp<<1; // 数据左移一位
}
}
/* 接收一字节子程序 */
void recbyte(uchar idata *ch)
{
uchar idata n=8; // 从SDA线上读取一位数据字节,共8位
uchar idata temp = 0;
while(n--)
{
SDA = 1;
SCL = 1;
temp = temp<<1; // 左移一位
if(SDA == 1)
temp = temp|0x01; // 若接收到的位为1,则数据的最后一位置1
else
temp = temp&0xfe; // 否则数据的最后一位置0
SCL=0;
}
*ch = temp;
}
/* 发送n字节数据子程序 */
void sendnbyte(uchar idata *sla, uchar n)
{
uchar idata *p;
start();
sendbyte(sla);
checkack();
if(F0 == 1) //这个F0是哪里来的?为什么这里是F0而不是nackFlag ?
{
NACK = 1;
return;
//NACK置位有什么用,在哪里控制MCU說应答有问题?Return被返回哪里去了? 程序下部执行哪个?
}
p = sbuf;
while(n--)
{
sendbyte(p);
checkack(); // 检查应答位
if (nackFlag == 1)
{
NACK=1;
return; // 若非应答表明器件错误或已坏,置错误标志位NACK
}
p++;
}
stop(); // 全部发完则停止
}
/* 接收n字节数据子程序 */
void recnbyte(uchar idata *sla, uchar n)
{
uchar idata *p;
start(); // 发送启动信号
sendbyte(sla); // 发送从器件地址字节
checkack(); // 检查应答位
if(nackFlag == 1)
{
NACK = 1;
return;
}
p = rbuf; // 接收字节存放在rbuf中
while(n--)
{
recbyte (p);
ack(); // 收到一个字节后发送一个应答位
p++;
}
n_ack(); // 收到最后一个字节后发送一个非应答位
stop();
}
/* 主函数,模拟实现I2C总线的数据收发 */
void main(void)
{
uchar i,numbyte;
numbyte = 8;
/* 需发送的8字节数据 */
for (i=0;i<numbyte;i++)
sbuf = i+0x11;
SLAdd = 0x58; // 从器件地址
sendnbyte(&SLAdd,numbyte); // 向从器件发送存放在sbuf中的8字节数据
for (i=0;i<10000;i++)
delay5us();
recnbyte(&SLAdd,numbyte); // 由从器件接收8字节数据,存放在rbuf中
} 程序隔开的中间部分为问题
另外程序中
定义的
bit bdata NACK 可否改为bit NACK ?
uchar idata sbuf 可否改为 uchar sbuf ?
SLAdd=0x58 是从器件地址? 如何解读? 查阅器件一般为0xa为固定然后是地址3位和一位读写, 还是說这个不是EEPROM器件,仅仅是一个IIC的通讯器件?
sendnbyte(&SLAdd,Numbyte) / & 在此有何意义? 建议你先仔细学习I2C的规程,彻底弄清楚基本的概念.另外你的许多基础也不牢固,如C语言,AVR的基本特点等.
如果你真要学习使用AVR,建议你买本我写的书《AVR单片机嵌入式系统原理与应用实践》,肯定回对你有帮助的. 代码太多重复
页:
[1]