📄 twi_usart.c
字号:
/********************************************************
存储一个字节,并读回校验,正确LED亮
EEPROM地址:0X00
TWI工作方式:查询方式
********************************************************/
#include <avr/io.h>
#include <avr/iom16.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include "TWI_USART.h"
#define uint unsigned int
#define uchar unsigned char
#define SLA_W 0xA0 //从机地址,主机写操作
#define SLA_R 0xA1 //从机地址,主机读操作
#define F_CPU 11059200
#define FSCL 100000
//TWI读写操作公共步骤
#define ST_FAIL 0 //出错状态
#define ST_START 1 //START状态检查
#define ST_SLAW 2 //SLAW状态检查
#define ST_WADDR 3 //ADDR状态检查
//TWI读操作步骤
#define ST_RESTART 4 //RESTART状态检查
#define ST_SLAR 5 //SLAR状态检查
#define ST_RDATA 6 //读取数据状态检查,循环n字节
//TWI写操作步骤
#define ST_WDATA 7 //写数据状态检查,循环n字节
#define FAIL_MAX 20 //重试次数最大值
/**********************I2C状态定义*************************/
/************************主机发送状态码********************/
#define TW_START 0x08 //START已发送
#define TW_REP_START 0x10 //重复START已发送
#define TW_MT_SLA_ACK 0x18 //SLA+W 已发送收到ACK
#define TW_MT_SLA_NACK 0x20 //SLA+W 已发送接收到NOT ACK
#define TW_MT_DATA_ACK 0x28 //数据已发送接收到ACK
#define TW_MT_DATA_NACK 0x30 //数据已发送接收到NOT ACK
#define TW_MT_ARB_LOST 0x38 //SLA+W 或数据的仲裁失败
/*************************主机接收状态码*****************/
//#define TW_START 0x08 //START已发送
//#define TW_REP_START 0x10 //重复START已发送
#define TW_MR_ARB_LOST 0x38 //SLA+R 或NOT ACK 的仲裁失败
#define TW_MR_SLA_ACK 0x40 //SLA+R 已发送接收到ACK
#define TW_MR_SLA_NACK 0x48 //SLA+R 已发送接收到NOT ACK
#define TW_MR_DATA_ACK 0x50 //接收到数据ACK 已返回
#define TW_MR_DATA_NACK 0x58 //接收到数据NOT ACK已返回
/************************从机接收状态码******************/
/*#define TW_SR_SLA_ACK 0x60 //自己的SLA+W 已经被接收ACK已返回
#define TW_SR_ARB_LOST_SLA_ACK 0x68 //SLA+R/W 作为主机的仲裁失败;自己的SLA+W 已经被接收ACK 已返回
#define TW_SR_GCALL_ACK 0x70 //接收到广播地址ACK 已返回
#define TW_SR_ARB_LOST_GCALL_ACK 0x78 //SLA+R/W 作为主机的仲裁失败;接收到广播地址ACK已返回
#define TW_SR_DATA_ACK 0x80 //以前以自己的SLA+W被寻址;数据已经被接收ACK已返回
#define TW_SR_DATA_NACK 0x88 //以前以自己的SLA+W被寻址;数据已经被接收NOT ACK已返回
#define TW_SR_GCALL_DATA_ACK 0x90 //以前以广播方式被寻址;数据已经被接收ACK已返回
#define TW_SR_GCALL_DATA_NACK 0x98 //以前以广播方式被寻址;数据已经被接收NOT ACK已返回
#define TW_SR_STOP 0xA0 //在以从机工作时接收到STOP或重复START
*/
/************************从发送状态码*******************/
/*
#define TW_ST_SLA_ACK 0xA8 //自己的SLA+R 已经被接收ACK 已返回
#define TW_ST_ARB_LOST_SLA_ACK 0xB0 //SLA+R/W 作为主机的仲裁失败;自己的SLA+R 已经被接收ACK 已返回
#define TW_ST_DATA_ACK 0xB8 //TWDR 里数据已经发送接收到ACK
#define TW_ST_DATA_NACK 0xC0 //TWDR 里数据已经发送接收到NOT ACK
#define TW_ST_LAST_DATA 0xC8 //TWDR 的一字节数据已经发送(TWAE = “0”);接收到ACK
*/
/****************************其它状态码*****************/
/*
#define TW_NO_INFO 0xF8 //没有相关的状态信息;TWINT = “0”
#define TW_BUS_ERROR 0x00 //由于非法的START 或STOP 引起的总线错误
*/
/*****************************************************/
void I2C_start(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA); //TWINT清零
while (!(TWCR & (1<<TWINT))); //0x08
}
/*****************************************************/
void I2C_stop(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}
/*****************************************************/
void I2C_write(uchar addr,uchar c)
{
TWDR = SLA_W;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x18
TWDR = addr;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x28
TWDR = c;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x18
}
/*****************************************************/
uchar I2C_read(uchar addr) //读一字节
{
uchar temp;
TWDR = SLA_W;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x18
TWDR = addr;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x28
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
while (!(TWCR & (1<<TWINT))); //0x10
TWDR = SLA_R;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x40
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //0x58
return(TWDR);
}
/****************************************************
函数名:TWI_init
作 用:TWI接口的初始化
*****************************************************/
void TWI_init(void)
{
PORTC = _BV(PC0); // i2c SCL
PORTC = _BV(PC1); // i2c SDA
TWAR = 0x00; //主机模式,该地址无效
TWSR = 0x00;
TWBR=(F_CPU/FSCL-16)/2; // TWI比特率
//TWBR = Baud_set; //100
//TWSR = P_value; //64分频
TWCR = 0x00; //关闭TWI模块
TWCR=(1<<TWEA)|(1<<TWEN); //允许ACK应答:On
}
/****************************************************/
void UartInit( )
{
//接收使能,发送使能,接收中断允许
UCSRB=(1<<RXCIE)|(1<<TXEN)|(1<<RXEN);
//UBRR=CK/(BUAD*16)-1,(CK=11.059MHz ATMEG16)
//1200 UBRRH=2; UBRRL=63; 575
//4800 UBRRH=0; UBRRL=143;
//9600 UBRRH=0; UBRRL=71;
//19200 UBRRH=0; UBRRL=35;
//38400 UBRRH=0; UBRRL=17;
//57600 UBRRH=0; UBRRL=11;
//115200 UBRRH=0; UBRRL=5;
//到目前为止,1200波特率还不能设置,原因是UBRRH写上进去东西
//UBRR=CK/(BUAD*16)-1,(CK=8.169984MHz ATMEG48)
//1200 UBRR0H=1; UBRR0L=0xA9;
//4800 UBRR0H=; UBRR0L=0x69;
//9600 UBRR0H=; UBRR0L=0x34;
//19200 UBRR0H=; UBRR0L=0x1A; 由于内部不是RC振荡器,所以高了不可取
//38400 UBRR0H=; UBRR0L=;
//57600 UBRR0H=; UBRR0L=;
//115200 UBRR0H=; UBRR0L=;
UBRRH=0; UBRRL=0x0C; //内部晶振,CK=1MHZ,UBRR=CK/(BUAD*16)-1
UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
/****************************************************/
//接收中断
SIGNAL(SIG_UART_RECV)
{
unsigned char c=UDR;
// if(c=='*') cRecState=1;
// else if(c=='A' && cRecState==1) cRecState=2;
// else if(c=='.' && cRecState==2) cGiveGift=1;
// else cRecState=0;
}
//发送中断
//SIGNAL(SIG_UART_TRANS)
//{
// if(--g_bTxdLen>0)
// UDR=g_aSendBuf[++g_bTxdPos];
//
//}
/****************************************************/
//从发送缓冲区发送指定长度的数据
void SendChar(unsigned char num)
{
while((UCSRA & (1<<UDRE))==0);
UDR=num;
}
/****************************************************/
//从接收缓冲去接收数据并返回
unsigned char RevChar ( void )
{
while ( (UCSRA & (1<<RXC))==0 );
return UDR;
}
/****************************************************/
int main (void)
{
uchar temp;
cli();
//Chip_init();
TWI_init();
_delay_ms(10);
UartInit();
sei();
_delay_ms(10);
while(1)
{
//写一个字节c到addr位置
I2C_start();
I2C_write(0x00,0x05);//addr,data
I2C_stop();
_delay_ms(50);
//读出刚才写入的数据
I2C_start();
temp = I2C_read(0x00);//addr
I2C_stop();
//如果读出的数据与写入相同,则亮灯,灯闪
if (temp == 0x05)
{
PORTA |=(1<<PA5);
DDRA |=(1<<PA5);//LED亮
_delay_ms(1000);
DDRA &=~(1<<PA5);//LED暗
_delay_ms(1000);
}
SendChar(temp);
uint b=0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -