📄 twi.c
字号:
/********************************
AVR单片机I/O口模拟I2C操作程序
文件名:twi.c
编译:WinAVR-20070122
硬件:CA-M8X
配置:外部4MHz
打开:S7(1,2,3) - EEPROM连接
S6(1,2) - 4MHz晶振连接
S5(5,6) - UART连接
注:PC5模拟SCL,PC4模拟SDA,PC3连接写保护引脚
芯艺设计室 2004-2007 版权所有
转载请保留本注释在内的全部内容
WEB: http://www.chipart.cn
Email: changfutong@sina.com
*******************************/
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
/*注:
AVR单片机I/O口模拟I2C总线时建议在外部连接上拉电阻
这样可通过改变I/O口输入输出方向的方式来设置高低
输出口保持不变(0)
此时如DDRX寄存器为1则变成输出0
若DDRX为0,则I/O口程高阻,但因外部的上拉电阻,总线相当于设置高
即通过设置DDRX的方式控制总线的高低
*/
#define SET_SCL DDRB&=~_BV(PB2)
#define CLR_SCL DDRB|=_BV(PB2)
#define SET_SDA DDRB&=~_BV(PB3)
#define CLR_SDA DDRB|=_BV(PB3)
#define SDA_PIN (PINB&_BV(PB3))
static void twi_delay_bus(void)
{
_delay_loop_2(10);
}
static void twi_ack(uint8_t ack)
{
if(!ack) //非应答
SET_SDA;
else //应答
CLR_SDA;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
CLR_SCL;
twi_delay_bus();
}
/*********以下为外部可调用的接口函数***********/
//初始化本模块
void TwiInit(void)
{
PORTB&=~(_BV(PB2)|_BV(PB3));
DDRB&=~(_BV(PB2)|_BV(PB3));
}
//产生启动信号
uint8_t TwiStart(void)
{
twi_delay_bus();
SET_SDA;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
CLR_SDA;
twi_delay_bus();
CLR_SCL;
twi_delay_bus();
return 1;
}
//产生停止信号
void TwiStop(void)
{
twi_delay_bus();
CLR_SDA;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
SET_SDA;
twi_delay_bus();
}
//向总线写一字节,并返回有无应答
uint8_t TwiWriteByte(uint8_t c)
{
uint8_t i,ack;
for(i=0;i<8;i++)
{
if(c&0x80)
SET_SDA;
else
CLR_SDA;
SET_SCL;
twi_delay_bus();
CLR_SCL;
c<<=1;
twi_delay_bus();
}
twi_delay_bus();
SET_SDA;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
if(SDA_PIN)
ack=0; //失败
else
ack=1;
CLR_SCL;
twi_delay_bus();
return ack;
}
//读一字节 ack: 1时应答,0时不应答
uint8_t TwiReadByte(uint8_t *c, uint8_t ack)
{
uint8_t i,ret;
ret=0;
SET_SDA;
for(i=0;i<8;i++)
{
twi_delay_bus();
CLR_SCL;
twi_delay_bus();
SET_SCL;
twi_delay_bus();
ret<<=1;
if(SDA_PIN)
ret++;
}
CLR_SCL;
twi_delay_bus();
twi_ack(ack);
*c=ret;
return(ret);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -