⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 twi_usart.c

📁 利用ATmega16对24c0进行读写操作
💻 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 + -