📄 i2c.c
字号:
/*****************************************/
/* Copyright (c) 2005, 通信工程学院 */
/* All rights reserved. */
/* 作 者:戴 佳 */
/*****************************************/
#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)
{
NACK = 1;
return; // 若非应答表明器件错误或已坏,置错误标志位NACK
}
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] = i+0x11;
SLAdd = 0x58; // 从器件地址
sendnbyte(&SLAdd,numbyte); // 向从器件发送存放在sbuf中的8字节数据
for (i=0;i<10000;i++)
delay5us();
recnbyte(&SLAdd,numbyte); // 由从器件接收8字节数据,存放在rbuf中
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -