完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
AVR TWI程序
i2c.h /**************************************************************************** title : C include file Software: AVR-GCC with AVR-AS Target: any AVR device *****************************************************************************/ #ifndef __I2C_DEV_H #define __I2C_DEV_H #define TWPS0 0 #define TWPS1 1 #define TWEN 2 #define TWIE 0 #define TWEA 6 #define TWINT 7 #define TWSTA 5 #define TWSTO 4 #define TWCR_CMD_MASK 0x0F #define TWSR_STATUS_MASK 0xF8 // return values #define I2C_OK 0x00 #define I2C_ERROR_NODEV 0x01 #define I2C_SEND_DATA_BUFFER_SIZE 0x10 #define I2C_RECEIVE_DATA_BUFFER_SIZE 0x10 //#define F_CPU 8000000 #define TRUE 1 #define FALSE 0 // types typedef enum { I2C_IDLE = 0, I2C_BUSY = 1, I2C_MASTER_TX = 2, I2C_MASTER_RX = 3, I2C_SLAVE_TX = 4, I2C_SLAVE_RX = 5 } eI2cStateType; unsigned char DevNum; void i2cInit(void); void i2cMasterSend(unsigned char deviceAddr, unsigned char length, unsigned char* data); void ClearReceiveBuf(void); #endif /* #ifndef __I2C_DEV_H */ /*######################################################################################################*/ /* T H E E N D */ /*######################################################################################################*/ i2c.c /**************************************************************************** Title : C file for the I2C FUNCTIONS library (i2c.c) Software: AVR-GCC with AVR-AS Target: any AVR device *****************************************************************************/ #i nclude #i nclude #i nclude #i nclude #i nclude "unit_main.h" #i nclude "i2c.h" // I2C标准波特率: // 低速 100KHz // 高速 400KHz // I2C 状态和地址变量 static volatile eI2cStateType I2cState; static unsigned char I2cDeviceAddrRW; // 发送缓冲区 static unsigned char I2cSendData[I2C_SEND_DATA_BUFFER_SIZE]; static unsigned char I2cSendDataIndex; static unsigned char I2cSendDataLength; // 接收缓冲区 static unsigned char I2cReceiveData[I2C_RECEIVE_DATA_BUFFER_SIZE]; static unsigned char I2cReceiveDataIndex; static unsigned char I2cReceiveDataLength; // 指向接收处理函数的指针,当本机被选中从接收时调用函数:I2cSlaveReceive static void (*i2cSlaveReceive)(unsigned char receiveDataLength, unsigned char* recieveData); // 指向发送处理函数的指针,当本机被选中从发送时调用函数:II2cSlaveTransmit static unsigned char (*i2cSlaveTransmit)(unsigned char transmitDataLengthMax, unsigned char* transmitData); //============================================================================== //设置总线速率 void i2cSetBitrate(unsigned int bitrateKHz) { unsigned char bitrate_div; // 计算分频 //SCL freq = F_CPU/(16+2*TWBR*4^TWPS) //TWPS = 00 bitrate_div = ((F_CPU/1000l)/bitrateKHz); if(bitrate_div >= 16) bitrate_div = (bitrate_div-16)/2; TWBR = bitrate_div; } //============================================================================== // 设置本机从地址 (从方式时) void i2cSetLocalDeviceAddr(unsigned char deviceAddr, unsigned char genCallEn) { TWAR=(deviceAddr&0xFE)|(genCallEn?1:0); } void i2cSetSlaveReceiveHandler(void (*i2cSlaveRx_func)(unsigned char receiveDataLength, unsigned char* recieveData)) { i2cSlaveReceive = i2cSlaveRx_func; } void i2cSetSlaveTransmitHandler(unsigned char (*i2cSlaveTx_func)(unsigned char transmitDataLengthMax, unsigned char* transmitData)) { i2cSlaveTransmit = i2cSlaveTx_func; } // 发送开始条件 inline void i2cSendStart(void) { TWCR = (TWCR&TWCR_CMD_MASK)|(1< // 发送停止条件,保持TWEA以便从接收 inline void i2cSendStop(void) { //TWCR &= ~(1< } // 等待i2c 总线操作完成 inline void i2cWaitForComplete(void) { while( !(TWCR&(1< inline void i2cSendByte(unsigned char data) { // 装载数据到 TWDR TWDR=data; // 发送开始 TWCR = (TWCR&TWCR_CMD_MASK)|(1< inline void i2cReceiveByte(unsigned char ackFlag) { //开始通过 i2c 接收 if( ackFlag ){ // ackFlag = TRUE: 数据接收后回应ACK TWCR = (TWCR&TWCR_CMD_MASK)|(1< // ackFlag = FALSE: 数据接收后无回应 TWCR = (TWCR&TWCR_CMD_MASK)|(1< } // 返回接收到的数据 inline unsigned char i2cGetReceivedByte(void) { return( TWDR ); } // 返回总线状态 inline unsigned char i2cGetStatus(void) { return(TWSR); } //============================================================================== void i2cMasterSend(unsigned char deviceAddr, unsigned char length, unsigned char* data) { unsigned char i; // 等待总线准备完成 while(I2cState); // 设置状态 I2cState = I2C_MASTER_TX; // 准备数据 I2cDeviceAddrRW = (deviceAddr & 0xFE); // RW 为0: 写操作 for(i=0; i I2cSendDataIndex = 0; I2cSendDataLength = length; // 发送开始条件 i2cSendStart(); while(I2cState); i2cSendStop(); } //============================================================================== void i2cMasterReceive(unsigned char deviceAddr, unsigned char length, unsigned char* data) { unsigned char i; // 等待总线准备完成 while(I2cState); // 设置状态 I2cState = I2C_MASTER_RX; // 保存数据 I2cDeviceAddrRW = (deviceAddr|0x01); // RW 为1 : 读操作 I2cReceiveDataIndex = 0; I2cReceiveDataLength = length; // 发送开始条件 i2cSendStart(); //等待数据准备好 while(I2cState); // 取数据 for(i=0; i } //============================================================================== unsigned char i2cMasterSendNI(unsigned char deviceAddr, unsigned char length, unsigned char* data) { unsigned char retval = I2C_OK; // 关I2C中断 TWCR&=~(1< i2cSendStart(); i2cWaitForComplete(); // 发送器件写地址 i2cSendByte( deviceAddr & 0xFE ); i2cWaitForComplete(); // 检查器件是否可用 if( TWSR == TW_MT_SLA_ACK){ // 发送数据 while(length) { i2cSendByte( *data++ ); i2cWaitForComplete(); length--; } }else{ // 如未回应器件地址,停止发送,返回错误 retval = I2C_ERROR_NODEV; } // 发送停止条件,保持TWEA以便从接收 i2cSendStop(); while( !(TWCR&(1< TWCR|=(1< } //============================================================================== unsigned char i2cMasterReceiveNI(unsigned char deviceAddr, unsigned char length, unsigned char *data) { unsigned char retval = I2C_OK; // 关I2C中断 TWCR&=~(1< i2cSendStart(); i2cWaitForComplete(); // 发送器件读地址 i2cSendByte( deviceAddr | 0x01 ); i2cWaitForComplete(); // 检查器件是否可用 if( TWSR == TW_MR_SLA_ACK){ // 接收数据并回应 while(length > 1){ i2cReceiveByte(TRUE); i2cWaitForComplete(); *data++ = i2cGetReceivedByte(); length--; } // 接收数据无回应 (末位信号) i2cReceiveByte(FALSE); i2cWaitForComplete(); *data++ = i2cGetReceivedByte(); }else{ // 如未回应器件地址,停止发送,返回错误 retval = I2C_ERROR_NODEV; } // 发送停止条件,保持TWEA以便从接收 i2cSendStop(); // 开I2C中断 TWCR|=TWIE; return retval; } //============================================================================== eI2cStateType i2cGetState(void) { return I2cState; } //============================================================================== // I2C (TWI) 中断服务程序 //interrupt [TWI] void twi_isr(void) SIGNAL(SIG_2WIRE_SERIAL) { //读状态位 unsigned char status; status = TWSR & TWSR_STATUS_MASK; switch(status) { // 主方式 case TW_START: // 0x08: START 已发送 case TW_REP_START: // 0x10: 重复START 已发送 // 发送器件地址 i2cSendByte(I2cDeviceAddrRW); break; // 主发送,主接收状态码 case TW_MT_SLA_ACK: // 0x18: SLA+W 已发送;接收到ACK case TW_MT_DATA_ACK: // 0x28: 数据已发送;接收到ACK if(I2cSendDataIndex < I2cSendDataLength) { // 发送数据 i2cSendByte( I2cSendData[I2cSendDataIndex++] ); }else{ // 发送停止条件,保持TWEA以便从接收 i2cSendStop(); // 设置状态 I2cState = I2C_IDLE; } break; case TW_MR_DATA_NACK: // 0x58: 接收到数据;NOT ACK 已返回 // 保存最终数据 I2cReceiveData[I2cReceiveDataIndex++] = TWDR; //继续发送条件 case TW_MR_SLA_NACK: // 0x48: SLA+R 已发送,接收到NOT ACK case TW_MT_SLA_NACK: // 0x20: SLA+W 已发送,接收到NOT ACK case TW_MT_DATA_NACK: // 0x30: 数据已发送,接收到NOT ACK // 发送停止条件,保持TWEA以便从接收 i2cSendStop(); // 设置状态 I2cState = I2C_IDLE; break; case TW_MT_ARB_LOST: // 0x38: SLA+W 或数据的仲裁失败 // 释放总线 TWCR = (TWCR&TWCR_CMD_MASK)|(1< I2cState = I2C_IDLE; break; case TW_MR_DATA_ACK: // 0x50: 接收到数据,ACK 已返回 // 保存接收到的数据位 I2cReceiveData[I2cReceiveDataIndex++] = TWDR; // 检查是否接收完 case TW_MR_SLA_ACK: // 0x40: SLA+R 已发送,接收到ACK if(I2cReceiveDataIndex < (I2cReceiveDataLength-1)) // 数据位将接收 , 回复 ACK (传送更多字节) i2cReceiveByte(TRUE); else // 数据位将接收 , 回复 NACK (传送最后字节) i2cReceiveByte(FALSE); break; // 从接收状态码 case TW_SR_SLA_ACK: // 0x60: 自己的SLA+W 已经被接收,ACK 已返回 case TW_SR_ARB_LOST_SLA_ACK: // 0x68: SLA+R/W 作为主机的仲裁失败;自己的SLA+W 已经被接收,ACK 已返回 case TW_SR_GCALL_ACK: // 0x70: 接收到广播地址,ACK 已返回 case TW_SR_ARB_LOST_GCALL_ACK: // 0x78: SLA+R/W 作为主机的仲裁失败;接收到广播地址,ACK 已返回 // 被选中为从写入 (数据将从主机接收) // 设置状态 I2cState = I2C_SLAVE_RX; // 缓冲准备 I2cReceiveDataIndex = 0; // 接收数据,回应 ACK TWCR = (TWCR&TWCR_CMD_MASK)|(1< case TW_SR_DATA_ACK: // 0x80: 以前以自己的 SLA+W 被寻址;数据已经被接收,ACK 已返回 case TW_SR_GCALL_DATA_ACK: // 0x90: 以前以广播方式被寻址;数据已经被接收,ACK 已返回 I2cReceiveData[I2cReceiveDataIndex++] = TWDR; //检查接收缓冲区状态 if(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE){ // 接收数据,回应 ACK i2cReceiveByte(TRUE); }else{ // 接收数据,回应 NACK i2cReceiveByte(FALSE); } break; case TW_SR_DATA_NACK: // 0x88: 以前以自己的 SLA+W 被寻址;数据已经被接收,NOT ACK 已返回 case TW_SR_GCALL_DATA_NACK: // 0x98: 以前以广播方式被寻址;数据已经被接收,NOT ACK 已返回 // 接收数据,回应 NACK i2cReceiveByte(FALSE); break; case TW_SR_STOP: // 0xA0: 在以从机工作时接收到STOP或重复START TWCR = (TWCR&TWCR_CMD_MASK)|(1< if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData); // 设置状态 I2cState = I2C_IDLE; break; // 从发送 case TW_ST_SLA_ACK: // 0xA8: 自己的SLA+R 已经被接收,ACK 已返回 case TW_ST_ARB_LOST_SLA_ACK: // 0xB0: SLA+R/W 作为主机的仲裁失败;自己的SLA+R 已经被接收,ACK 已返回 // 被选中为从读出 (数据将从传回主机) // 设置状态 I2cState = I2C_SLAVE_TX; // 数据请求 if(i2cSlaveTransmit) I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData); I2cSendDataIndex = 0; // case TW_ST_DATA_ACK: // 0xB8: TWDR 里数据已经发送,接收到ACK // 发送数据位 TWDR=I2cSendData[I2cSendDataIndex++]; if(I2cSendDataIndex < I2cSendDataLength) // 回应 ACK TWCR = (TWCR&TWCR_CMD_MASK)|(1< // 回应 NACK TWCR =(TWCR&TWCR_CMD_MASK)|(1< case TW_ST_DATA_NACK: // 0xC0: TWDR 里数据已经发送接收到NOT ACK case TW_ST_LAST_DATA: // 0xC8: TWDR 的一字节数据已经发送(TWAE = “0”);接收到ACK // 全部完成 // 从方式开放 TWCR = (TWCR&TWCR_CMD_MASK)|(1< I2cState = I2C_IDLE; break; case TW_NO_INFO: // 0xF8: 没有相关的状态信息;TWINT = “0” // 无操作 break; case TW_BUS_ERROR: // 0x00: 由于非法的START 或STOP 引起的总线错误 // 内部硬件复位,释放总线 TWCR = (TWCR&TWCR_CMD_MASK)|(1< I2cState = I2C_IDLE; break; } } //============================================================================== // 从操作 void i2cSlaveReceiveService(unsigned char receiveDataLength, unsigned char* receiveData) { unsigned char i; //此函数在本机被选中为从写入时运行 // 接收到的数据存入本地缓冲区 for(i=0; i } localBufferLength = receiveDataLength; // SysStatus = SLA_RECEIVE; } //============================================================================== unsigned char i2cSlaveTransmitService(unsigned char transmitDataLengthMax, unsigned char* transmitData) { unsigned char i; //此函数在本机被选中为从读出时运行 //要发送的数据存入发送缓冲区 for(i=0; i } //localBuffer[0]++; return localBufferLength; } //============================================================================== void ClearReceiveBuf(void) { unsigned char i; for(i=0;i } //============================================================================== //总线初始化 void i2cInit(void) { //设置总线上拉 PORTC = _BV(PC0); // i2c SCL PORTC = _BV(PC1); // i2c SDA // 清空从发送和从接受 i2cSlaveReceive = 0; i2cSlaveTransmit = 0; // 设置 i2c 波特率为 100KHz //i2cSetBitrate(30); TWBR = 18; //F_CPU =16000000 //TWBR = 8; //F_CPU =8000000 // I2C总线使能 TWCR|=1< I2cState = I2C_IDLE; // 开I2C中断和回应 TWCR|=1< //DevNum = 1; i2cSetLocalDeviceAddr(1,0); //设置从接收函数句柄(此函数在被选中为从接收时执行) i2cSetSlaveReceiveHandler( i2cSlaveReceiveService ); //设置从发送函数句柄(此函数在被选中为从发送时执行) i2cSetSlaveTransmitHandler( i2cSlaveTransmitService ); sei(); } /*############################################################################*/ /* T H E E N D */ /*############################################################################*/ |
|
相关推荐 |
|
只有小组成员才能发言,加入小组>>
AVR Atmega16 Bootloader程序与上位机LabView程序
5122 浏览 6 评论
#include <ioavr.h>这个头文件我应该下什么编译器
7767 浏览 0 评论
3026 浏览 2 评论
3103 浏览 1 评论
10053 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 06:09 , Processed in 0.364024 second(s), Total 41, Slave 31 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号