下面我就以《 AVR 单片机入门与实践 》李弘 等编著 北京航空航天大学出版社这本书来讲述学习心得
I2C技术已经有数百种芯片支持,所以学会它对于我们单片机外围硬件的设计更是如虎添翼。Mega8有TWI模块,但这章我们先用IO口模拟i2c通信。一步一步的来,TWI后面的章节会介绍的,先把基础打牢。
第十章:模拟i2c技术
看P162到P163页,关于TWI的部分可先不看。P269 P270看看利用系统i2c函数的例子,仔细推敲一下,其实利用系统函数,i2c程序可以编写的 再严密或者说抗干扰强的 程序。我写的程序只起抛砖引玉的作用。
然后再在网上搜一些关于I2C原理的资料看看,马潮老师写的 《AVR单片机嵌入式系统原理与应用实践》 北京航天航空大学出版社出版 这本数的i2c讲解很深刻,如果有的话,建议仔细看看
I2c的最主要准则就是 scl为高电平时,sda不能改变。(起始和结束信号除外)----------i2c的精髓,深刻理解此句话。
硬件电路上sda和scl最好加上上拉电阻(4K7 到10K),虽然mega8 IO口有上拉电阻(可使能可禁止),但考虑到sda线有时做输入有时做输出,IO方向变换的时候很容易出错(如果上拉电阻考虑不周全)。
说明:
在Mega8学习笔记(10.1)里我会用采用CVAVR自带的I2C系统函数写24C02
在Mega8学习笔记(10.2)里我会用像51单片机那样写24C02的方法来写i2c
在Mega8学习笔记(10.3)里我会用avr单片机独特的方式写24C02
以上三种方法均是IO口模拟I2C
//现象 PORTB口的小灯隔一个亮一个(PORTB=0X55)
//先在0x05地址中写0x55;在读出0x55地址的内容反映在PORTB口上
//此程序我在我设计的开发板上运行调试过,现象正常
// 采用CVAVR自带的I2C系统函数
/*****************************************************
Chip type : ATmega8L
Program type : Application
IDWE : CVAVR
Clock frequency : 8.000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*****************************************************/
//----------------------------------------------------
//头文件
#i nclude <mega8.h>
#i nclude <delay.h>
//系统I2C的头文件
#i nclude <i2c.h>
//----------------------------------------------------
//----------------------------------------------------
//符号替换声明
//24C02的地址
#define EEPROM_BUS_ADDRESS 0XA0
//变量类型符号替换
#define u8 unsigned char
//----------------------------------------------------
//----------------------------------------------------
//定义SCL SDA 注意:SCL 和SDA 必须来自于同一个IO口组
//我用的是PORTC.5 和 PORTC.4 ( .equ __i2c_port =0x15 注:PORTC口的硬件地址就是0x15 )
#asm
.equ __i2c_port =0x15
.equ __sda_bit =5
.equ __scl_bit =4
#endasm
//----------------------------------------------------
//----------------------------------------------------
//读24c02
u8 eeprom_read(u8 address)//读函数
{
u8 data;
while (! i2c_start()) //起始信号 该函数返回1则说明总线空闲 可以i2c操作
{
;
}
i2c_write(EEPROM_BUS_ADDRESS); //写 从机地址 方向:写
i2c_write(address); //写 读取地址
while (! i2c_start()) //起始信号 该函数返回1则说明总线空闲 可以i2c操作
{
;
}
i2c_write(EEPROM_BUS_ADDRESS|0x01); //写 从机地址 方向:读
data=i2c_read(0); //读取内容 并返回 ack=0
i2c_stop(); //停止信号
return data; //函数返回值是读取的内容
}
//----------------------------------------------------
//----------------------------------------------------
void eeprom_write(u8 address,u8 data) //写函数
{
while (! i2c_start()) //起始信号 该函数返回1则说明总线空闲 可以i2c操作
{
;
}
i2c_write(EEPROM_BUS_ADDRESS); //写 从机地址 方向:写
i2c_write(address); //写 写地址
i2c_write(data); //写 内容
i2c_stop(); //停止信号
delay_ms(15); //延时15ms 等待写操作完成
}
//----------------------------------------------------
//----------------------------------------------------
void init(void) //IO口初始化
{
DDRB=0XFF;
PORTB=0xFF;
ACSR=0x80; //关比较器电源
}
//----------------------------------------------------
//----------------------------------------------------
void main(void)
{
i2c_init(); //i2c初始化
init(); //IO初始化
eeprom_write(0x05, 0X55); //写
PORTB= eeprom_read(0x05); //读
while (1)
{
; //工作结束,原地踏步
}
}
//----------------------------------------------------