|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2008-8-12 12:59:32
|
显示全部楼层
附程序如下
//ATmega16L
//基于CVAVR
//8MHZ晶振
//基于16L硬件I2C实现
//利用PC显示器做调试用窗口
//PC1--SDA
//PC0--SCL
#include <mega16.h>
#include <stdio.h> //通用串行异步总线 要用到
#include <delay.h>
#define uchar unsigned char
#define BUS_ADDR 0xa0 //24c02 所在地址
//TWI 状态寄存器TWSR设置项
//预分频率设置
#define TWPS0 (1<<0)
#define TWPS1 (1<<1)
//控制寄存器TWCR设置项
#define TWEN (1<<2)
#define TWIE (1<<0)
#define TWEA (1<<6)
#define TWINT (1<<7)
#define TWSTA (1<<5)
#define TWSTO (1<<4)
//状态字设置
#define TW_START 0x08
#define REP_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_nACK 0x20
#define MT_DAT_ACK 0x28
#define MT_DAT_nACK 0x30
#define LOST 0x38
#define MR_SLA_ACK 0x40
#define MR_SLA_nACK 0x48
#define MR_DAT_ACK 0x50
#define MR_DAT_nACK 0x58
//24C02 相关 内存空间为 000H~7ffH
#define Page_size 8 //256 个 页面 每个页面8 个 字节
#define Page_mask Page_size-1 //页内
void I2C_init(void)
{
TWSR=0x00; //清状态
TWBR=0x00; //复位值
TWAR=0x00; //
TWCR=TWIE|TWEA;//ACK Enable and TWI ENABLE
}
uchar I2C_start(void)
{
TWCR=TWEN|TWSTA|TWINT; //先清出INT 标志位
while(!(TWCR&TWINT)); //当TWINT be set to"1",marked finished the current job
return 1;
}
void I2C_stop(void)
{
TWCR=TWEN|TWSTO|TWINT;
}
uchar I2C_write(uchar c)
{
uchar ack=1;
TWDR = c;
TWCR = TWINT|TWEN;
while (!(TWCR & TWINT));
if((TWSR & 0xF8) != MT_SLA_ACK)
ack = 0;
return ack;
}
uchar I2C_read(unsigned char ack) //读一字节 ack: 1时应答,0时不应答
{
if (ack)
TWCR = TWINT|TWEN|TWEA;
else
TWCR = TWINT|TWEN;
while (!(TWCR & TWINT));
return(TWDR);
}
void EEprom_Page_write(unsigned int Addr,unsigned char n, unsigned char* arr)
{
unsigned char i;
I2C_start(); // 发起始信号
I2C_write(BUS_ADDR); // 发写从机写寻址字节
I2C_write(Addr>>8); // 发存储单元地址高字节
I2C_write(Addr); // 发存储单元地址低字节
for (i=1;i<=n;i++)
{
I2C_write(*arr); // 写一个字节数据到24C02
arr++;
}
I2C_stop(); // 发停止信号
delay_ms(10); // 等待10ms,保证24C02内部写操作完成再进行新操作
}
void EEprom_Write(unsigned int Addr,unsigned char n, unsigned char* arr)
{
unsigned char n_tmp;
n_tmp=Page_size-(unsigned char)(Addr&Page_mask); //页内剩余字节数
if ((n>n_tmp)&&(n_tmp!=0)) //还剩空间, 但不够写完
{
EEprom_Page_write(Addr,n_tmp,arr); //先写完剩余空间
Addr += n_tmp;
n -= n_tmp;
arr += n_tmp;
}
while (n >= Page_size) //未写完的数据超过一页的,
{
EEprom_Page_write(Addr,Page_size, arr);
Addr += Page_size;
n -= Page_size;
arr += Page_size;
}
if (n!=0) //还剩的未写完的数据,不足一页的
EEprom_Page_write(Addr,n,arr);
}
void EEprom_read(unsigned int Addr,unsigned char n, unsigned char* arr)
{
unsigned char i;
I2C_start(); // 发起始信号
I2C_write(BUS_ADDR); // 发写从机写寻址字节
I2C_write(Addr>>8); // 发存储单元地址高字节
I2C_write(Addr); // 发存储单元地址低字节
I2C_start(); // 发起始信号
I2C_write(BUS_ADDR+ 1); // 发从机读寻址字节
for (i=1;i<=n-1;i++)
{
*arr = I2C_read(1); // 读一个字节数据,返回ACK
arr++;
}
*arr=I2C_read(0); // 读最后一个字节数据,返回NO ACK
I2C_stop(); // 发停止信号
}
void main(void)
{
unsigned char i,data[100];
UCSRA=0x00; // USART initialization
UCSRB=0x18; // Communication Parameters: 8 Data, 1 Stop, No Parity
UCSRC=0x86; // USART Receiver: On,USART Transmitter: On
UBRRH=0x00; // USART Mode: Asynchronous ,USART Baud Rate: 9600
UBRRL=0x33;
// ================================================
I2C_init(); // initialize the I2C bus
for (i=0;i<100;i++) {data=8;} // 数组赋值
EEprom_Write(0x001,100,data);
for (i=0;i<100;i++) {data=0;} // 数组清零
EEprom_read(0x001,100,data);
for (i=0;i<100;i++) {putchar(data);} // 送PC检验
while (1){};
} |
|