|
本帖最后由 js200300953 于 2012-6-24 15:50 编辑
这个库是NUC140的,应该很容易就可以移植到其他芯片上(其实这个库是从AVRi移植过来的),特别是同为M3的STM32。
希望对大家有帮助。
废话少说,上代码。
这是头文件:- /* lib/bus/i2c/i2c.h
- * 2012-5-11 16:05:24 */
- #ifndef __FILE_LIB_BUS_I2C_I2C_H__
- #define __FILE_LIB_BUS_I2C_I2C_H__
- #include "NUC1xx.h"
- #include "../../common/common.h"
- /* 数据传输回调函数。
- * 每(准备)传输一个字节都调用一次。
- * 参数:
- * seq => 序号,第一次调用时为0,以后每次调用递增。
- * data => seq==0时写(从机地址+W/R)到data。
- * seq!=0时data是数据。发送就写data,接收就读data。
- * 返回值表示下一步的行为:
- * I2C_RT_START => 发送开始信号。
- * I2C_RT_STOP => 发送停止信号。
- * I2C_RT_REPEAT_START_OR_STOP => 如果有下一次传输,就发送RepeatStart,否则发送Stop。
- * I2C_RT_ACK => 继续传送,回应ACK。
- * I2C_RT_NACK => 继续传送,回应NACK。 */
- typedef uint8_t (* I2C_transmitCallback)(uint8_t seq,uint8_t * data);
- /* 异常回调函数。
- * 总线出现异常就会被调用。
- * 参数:
- * exception => 异常类型,{I2C_EXCEPTION_NACK,I2C_EXCEPTION_ARBITRATION_LOST}。
- * 返回值表示下一步的行为:
- * I2C_RT_START => 发送开始信号。
- * I2C_RT_STOP => 发送停止信号,终止传输(推荐)。
- * I2C_RT_ACK => 继续传送,回应ACK。
- * I2C_RT_NACK => 继续传送,回应NACK。 */
- typedef uint8_t (* I2C_exceptionCallback)(uint8_t exception);
- enum {I2C_EXCEPTION_NACK,I2C_EXCEPTION_ARBITRATION_LOST};
- #define I2C_NO_CALLBACK 0
- #define I2C_isCallback(cb) ((cb) != I2C_NO_CALLBACK)
- /* 包装变量的结构体。*/
- typedef struct
- {
- I2C_transmitCallback transmitCallback;
- I2C_transmitCallback nextCallback;
- I2C_exceptionCallback exceptionCallback;
- uint32_t curSeq : 7;
- uint32_t isIdle : 1;
- }I2C_t;
- /*
- * 函数声明。 */
- void I2C_init (uint8_t which,uint32_t rate);
- uint8_t I2C_transmit (uint8_t which,I2C_transmitCallback cb);
- uint8_t I2C_isIdle (uint8_t which);
- void I2C_setNextCallback (uint8_t which,I2C_transmitCallback cb);
- void I2C_setExceptionCallback (uint8_t which,I2C_exceptionCallback cb);
- //
- void I2C_IRQHandler (uint8_t which);
- void I2C_actionStart (uint8_t which);
- void I2C_actionStop (uint8_t which);
- void I2C_actionAck (uint8_t which);
- void I2C_actionNack (uint8_t which);
- void I2C_actionStart_notInIRQ (uint8_t which);
- /* 用7位的地址构造(地址+W/R)字节。*/
- #define I2C_addressToByte_write(addr7) ((addr7)<<1)
- #define I2C_addressToByte_read(addr7) (((addr7)<<1) | 1)
- /*
- * 函数返回值。
- * RT : return */
- enum
- {
- I2C_RT_IS_IDLE_NO = 0,
- I2C_RT_IS_IDLE_YES = 1
- };
- enum
- {
- I2C_RT_TRANSMIT_NORMAL = 0,
- I2C_RT_TRANSMIT_BUSY,
- I2C_RT_TRANSMIT_ERROR,
- };
- enum
- {
- I2C_RT_START,
- I2C_RT_REPEAT_START_OR_STOP,
- I2C_RT_STOP,
- I2C_RT_ACK,
- I2C_RT_NACK,
- };
- /*
- * 总线状态。
- * ST : status
- * MA : master
- * MT : master transmit
- * MR : master receive */
- enum
- {
- I2C_ST_MA_STARTED = 0x08,
- I2C_ST_MA_REPEAT_STARTED = 0x10,
- I2C_ST_MT_ADDR_ACK = 0x18,
- I2C_ST_MT_ADDR_NACK = 0x20,
- I2C_ST_MT_DATA_ACK = 0x28,
- I2C_ST_MT_DATA_NACK = 0x30,
- I2C_ST_MA_ARBITRATION_LOST = 0x38,
- I2C_ST_MR_ADDR_ACK = 0x40,
- I2C_ST_MR_ADDR_NACK = 0x48,
- I2C_ST_MR_DATA_ACK = 0x50,
- I2C_ST_MR_DATA_NACK = 0x58,
- I2C_ST_ERROR = 0x00,
- };
- #endif // __FILE_LIB_BUS_I2C_I2C_H__
复制代码 然后是代码:- /* lib/bus/i2c/i2c.c
- * 2012-5-11 16:04:52 */
- #include "NUC1xx.h"
- #include "../../common/common.h"
- #include "i2c.h"
- /*
- * 定义变量 */
- I2C_T * const I2C_Base[2] = {I2C0,I2C1};
- volatile static I2C_t I2C_var[2];
- /*
- * 初始化I2C。
- * 参数
- * which => 指定总线,{0,1}。
- * rate => 时钟,kHz,[48,12000]。基于48Mhz的系统时钟。*/
- void I2C_init(uint8_t which,uint32_t rate)
- {
- if(which == 0)
- {
- /*
- * 设置针脚功能。 */
- SYS->GPAMFP.I2C0_SCL = 1;
- SYS->GPAMFP.I2C0_SDA = 1;
- /*
- * 允许中断。 */
- NVIC_ISER->I2C0_INT = 1;
- /*
- * 通入时钟。 */
- SYSCLK->APBCLK.I2C0_EN = 1;
- }
- else if(which == 1)
- {
- /*
- * 设置针脚功能。 */
- SYS->GPAMFP.I2C1_SCL_nRD = 1;
- SYS->GPAMFP.I2C1_SDA_nWR = 1;
- SYS->ALTMFP.EBI_EN = 0;
- /*
- * 允许中断。 */
- NVIC_ISER->I2C1_INT = 1;
- /*
- * 通入时钟。 */
- SYSCLK->APBCLK.I2C1_EN = 1;
- }
- I2C_var[which].isIdle = 1;
- I2C_var[which].transmitCallback = I2C_NO_CALLBACK;
- I2C_var[which].nextCallback = I2C_NO_CALLBACK;
- I2C_var[which].exceptionCallback = I2C_NO_CALLBACK;
- /*
- * 设置时钟。 */
- I2C_Base[which]->u32I2CLK = 12000 / rate - 1;
- }
- /* 判断I2C是否空闲。
- * 参数
- * which => 指定总线,{0,1}。*/
- uint8_t I2C_isIdle(uint8_t which)
- {
- return I2C_var[which].isIdle;
- }
- /*
- * 传送数据,异步。
- * 参数
- * which => 指定总线,{0,1}。
- * cb => 回调函数,传送是发送还是接收,取决于回调函数的具体实现。
- * 返回值
- * I2C_RT_TRANSMIT_NORMAL => 正常。但不保证发送成功。
- * I2C_RT_TRANSMIT_BUSY => 总线忙。
- * I2C_RT_TRANSMIT_ERROR => 指定的总线不存在。*/
- uint8_t I2C_transmit(uint8_t which,I2C_transmitCallback cb)
- {
- if(!I2C_isIdle(which))
- return I2C_RT_TRANSMIT_BUSY;
- I2C_var[which].isIdle = 0;
- //
- if(which > 1)
- return I2C_RT_TRANSMIT_ERROR;
- //
- I2C_var[which].transmitCallback = cb;
- I2C_var[which].nextCallback = I2C_NO_CALLBACK;
- I2C_var[which].exceptionCallback = I2C_NO_CALLBACK;
- //
- I2C_actionStart(which);
- return I2C_RT_TRANSMIT_NORMAL;
- }
- /*
- * 设置下一个任务。
- * 用于连续传输,中间是Repeat Start,而不是Stop。
- * 本次传输有效,下次调用I2C_transmit()时会重置。 */
- void I2C_setNextCallback(uint8_t which,I2C_transmitCallback cb)
- {
- I2C_var[which].nextCallback = cb;
- }
- /*
- * 设置错误回调函数。
- * 详细见I2C_transmitCallback的定义。
- * 本次传输有效,下次调用I2C_transmit()时会重置。 */
- void I2C_setExceptionCallback(uint8_t which,I2C_exceptionCallback cb)
- {
- I2C_var[which].exceptionCallback = cb;
- }
- /*
- * I2C通用中断处理函数。
- * 参数
- * which => 指定总线。 */
- void I2C_IRQHandler(uint8_t which)
- {
- /*
- * 根据总线状态决定下一步动作。 */
- uint8_t action = I2C_RT_REPEAT_START_OR_STOP;
- switch(I2C_Base[which]->I2CSTATUS)
- {
- case I2C_ST_MA_STARTED :
- case I2C_ST_MA_REPEAT_STARTED :
- /* Start信号已发出,初始化计数,发送(地址+W/R)。 */
- I2C_var[which].curSeq = 0;
- action = I2C_var[which].transmitCallback(I2C_var[which].curSeq,
- (uint8_t *)&(I2C_Base[which]->u32I2CDAT));
- break;
- case I2C_ST_MT_ADDR_ACK :
- case I2C_ST_MT_DATA_ACK :
- case I2C_ST_MR_DATA_ACK :
- /* 处理数据和获取下一步动作。 */
- I2C_var[which].curSeq ++;
- action = I2C_var[which].transmitCallback(I2C_var[which].curSeq,
- (uint8_t *)&(I2C_Base[which]->u32I2CDAT));
- break;
- case I2C_ST_MR_ADDR_ACK :
- /* 接收模式,发送完地址,直接ACK就可以。 */
- action = I2C_RT_ACK;
- break;
- case I2C_ST_MT_ADDR_NACK :
- case I2C_ST_MT_DATA_NACK :
- case I2C_ST_MR_ADDR_NACK :
- /* 发送数据后收到NACK,默认动作是Stop。 */
- if(I2C_isCallback(I2C_var[which].exceptionCallback))
- action = I2C_var[which].exceptionCallback(I2C_EXCEPTION_NACK);
- else
- action = I2C_RT_REPEAT_START_OR_STOP;
- break;
- case I2C_ST_MR_DATA_NACK :
- /* 如果接收数据时响应了NACK,自动Stop。 */
- action = I2C_RT_REPEAT_START_OR_STOP;
- break;
- case I2C_ST_MA_ARBITRATION_LOST :
- /* 总线失控,默认等待重新开始。*/
- if(I2C_isCallback(I2C_var[which].exceptionCallback))
- action = I2C_var[which].exceptionCallback(I2C_EXCEPTION_ARBITRATION_LOST);
- else
- action = I2C_RT_START;
- break;
- case I2C_ST_ERROR :
- default :
- action = I2C_RT_STOP;
- break;
- }
- /*
- * 执行动作。 */
- switch(action)
- {
- case I2C_RT_START :
- I2C_actionStart(which);
- break;
- case I2C_RT_REPEAT_START_OR_STOP :
- /* 检查有没有连续的任务,有就Repeat Start,否则Stop。 */
- if(I2C_isCallback(I2C_var[which].nextCallback))
- {
- I2C_var[which].transmitCallback = I2C_var[which].nextCallback;
- I2C_var[which].nextCallback = I2C_NO_CALLBACK;
- I2C_actionStart(which);
- }
- else
- {
- I2C_actionStop(which);
- }
- break;
- case I2C_RT_STOP :
- I2C_actionStop(which);
- break;
- case I2C_RT_ACK :
- I2C_actionAck(which);
- break;
- case I2C_RT_NACK :
- I2C_actionNack(which);
- break;
- }
- }
- /*
- * I2C0中断处理函数。 */
- void I2C0_IRQHandler(void)
- {
- I2C_IRQHandler(0);
- }
- /*
- * I2C1中断处理函数。 */
- void I2C1_IRQHandler(void)
- {
- I2C_IRQHandler(1);
- }
- void I2C_actionStart(uint8_t which)
- {
- I2C_Base[which]->u32I2CON = (_BV(3)|_BV(6)|_BV(7)|_BV(5));
- }
- void I2C_actionStop(uint8_t which)
- {
- I2C_Base[which]->u32I2CON = (_BV(3)|_BV(6)|_BV(7)|_BV(4));
- I2C_var[which].isIdle = 1;
- }
- void I2C_actionAck(uint8_t which)
- {
- I2C_Base[which]->u32I2CON = (_BV(3)|_BV(6)|_BV(7)|_BV(2));
- }
- void I2C_actionNack(uint8_t which)
- {
- I2C_Base[which]->u32I2CON = (_BV(3)|_BV(6)|_BV(7));
- }
- void I2C_actionStart_notInIRQ(uint8_t which)
- {
- I2C_Base[which]->u32I2CON = (_BV(6)|_BV(7)|_BV(5));
- }
复制代码 接口只有5个函数:- void I2C_init (uint8_t which,uint32_t rate);
- uint8_t I2C_transmit (uint8_t which,I2C_transmitCallback cb);
- uint8_t I2C_isIdle (uint8_t which);
- void I2C_setNextCallback (uint8_t which,I2C_transmitCallback cb);
- void I2C_setExceptionCallback (uint8_t which,I2C_exceptionCallback cb);
复制代码 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|