EFM32 硬件I2C操作
来源:互联网 发布:网络诗选 编辑:程序博客网 时间:2024/04/29 03:28
有关的例程,请参考如下:
#include "efm32.h"#include "em_chip.h"#include "em_cmu.h"#include "em_emu.h"#include "em_gpio.h"#include "em_i2c.h"#include "I2C_hw.h"unsigned long i2c_error = 0;void I2C_WaitForAck(void);void I2C_Buslock_Process(void);void I2C_IO_Initial(void){ i2c_error = 0; /* Enabling clock to the I2C, GPIO*/ CMU_ClockEnable(cmuClock_GPIO, true); CMU_ClockEnable(cmuClock_I2C0, true); /* Using PC6 (SDA) and PC7 (SCL) */ GPIO_PinModeSet(gpioPortD, 6, gpioModeWiredAndPullUpFilter, 1); GPIO_PinModeSet(gpioPortD, 7, gpioModeWiredAndPullUpFilter, 1); /* Enable pins at location 2 */ I2C0->ROUTE = (I2C_ROUTE_SDAPEN |I2C_ROUTE_SCLPEN |I2C_ROUTE_LOCATION_LOC1); I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX | I2C_CMD_ABORT; I2C0->CTRL &= ~_I2C_CTRL_MASK; /* Set the CLHR (clock low to high ratio). */ I2C0->CTRL |= i2cClockHLRStandard <<_I2C_CTRL_CLHR_SHIFT; // Set SCK clock low timeout and bus idle timeout I2C0->CTRL |= I2C_CTRL_CLTO_1024PPC | I2C_CTRL_GIBITO | I2C_CTRL_BITO_160PCC; // Set auto STOP when NACK I2C0->CTRL |= I2C_CTRL_AUTOSN; /* Frequency is given by fSCL = fHFPERCLK/((Nlow + Nhigh)(DIV + 1) + 4), thus */ /* DIV = ((fHFPERCLK - 4fSCL)/((Nlow + Nhigh)fSCL)) - 1 */ //Assume system clock = 1000000, i2c clock = 30kHz; //div = (1000000 - (4 * 30000)) / (8 * 30000) = 3.67 = 4; //CLKDIV = div - 1; I2C0->CLKDIV = 16; NVIC_ClearPendingIRQ(I2C0_IRQn); I2C0->IFC = _I2C_IFC_MASK; //I2C0->IEN = I2C_IEN_ARBLOST | I2C_IEN_CLTO | I2C_IEN_BITO | I2C_IEN_NACK | I2C_IEN_BUSERR; //NVIC_EnableIRQ(I2C0_IRQn); BITBAND_Peripheral(&(I2C0->CTRL),_I2C_CTRL_EN_SHIFT,true);}unsigned char I2C_SentData(unsigned char Address, unsigned short Offset, unsigned char Data){ //Perpare for a new transmit I2C0->CMD = I2C_CMD_ABORT; I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX; //Clear all the flags I2C0->IFC = _I2C_IFC_MASK; //Begin to transmit I2C0->CMD = I2C_CMD_START; //Start I2C0->TXDATA = Address | I2C_WRITE_COMMAND; //I2C hardware address I2C_WaitForAck(); I2C0->TXDATA = Offset; //I2C internal address I2C_WaitForAck(); I2C0->TXDATA = Data; //I2C data I2C_WaitForAck(); I2C0->CMD = I2C_CMD_STOP; //Stop unsigned char Result = i2c_error; i2c_error = 0; return Result;}unsigned char I2C_ReadData(unsigned char Address, unsigned short Offset, unsigned char *Rx){ //Perpare for a new transmit I2C0->CMD = I2C_CMD_ABORT; I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX; //Clear all the flags I2C0->IFC = _I2C_IFC_MASK; //Begin to transmit I2C0->CMD = I2C_CMD_START; //S I2C0->TXDATA = Address | I2C_WRITE_COMMAND; //AD+W hardware address I2C_WaitForAck(); I2C0->TXDATA = Offset; //internal register address I2C_WaitForAck(); I2C0->CMD = I2C_CMD_START; //S I2C0->TXDATA = Address | I2C_READ_COMMAND; //AD+R internal register address I2C_WaitForAck(); while(!((I2C0->IF) & I2C_IF_RXDATAV)); *Rx = (unsigned char)(I2C0->RXDATA); I2C0->CMD = I2C_CMD_NACK; //NACK I2C0->CMD = I2C_CMD_STOP; //P unsigned char Result = i2c_error; i2c_error = 0; return Result;}void I2C_WaitForAck(void){ while(!((I2C0->IF) & I2C_IF_ACK)) { //STOP auto send if(i2c_error) { break; } } I2C0->IFC = _I2C_IFC_MASK;}void I2C0_IRQHandler(void){ static unsigned char Arblost = 0; unsigned long Flag = I2C0->IF; if(Flag & I2C_IF_NACK) { //auto STOP send i2c_error = 1; } if(Flag & I2C_IF_BUSERR) { I2C0->CMD = I2C_CMD_ABORT; I2C0->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX; i2c_error = 1; } if(Flag & I2C_IF_ARBLOST) { //arbitration losses, maybe SDA is stuck if(Arblost++ > 5) { Arblost = 0; I2C_Buslock_Process(); } i2c_error = 1; } if((Flag & I2C_IF_CLTO) || (Flag & I2C_IF_BITO)) { I2C_Buslock_Process(); i2c_error = 1; } I2C0->IFC = Flag;}void I2C_Buslock_Process(void){ unsigned long Delay = 1000; //Disable I2C module, and clearing the route register BITBAND_Peripheral(&(I2C0->CTRL),_I2C_CTRL_EN_SHIFT,false); I2C0->ROUTE = 0; //Set as pushpull mode GPIO_PinModeSet(gpioPortD, 6, gpioModePushPull, 1);//SDA GPIO_PinModeSet(gpioPortD, 7, gpioModePushPull, 1);//SCL //send 9 clock of SCL for(unsigned char i = 0; i < 9; i++) { Delay = 3000; GPIO_PinOutClear(gpioPortD, 7); while(Delay--); Delay = 3000; GPIO_PinOutSet(gpioPortD, 7); while(Delay--); } /* Using PD6 (SDA) and PD7 (SCL) */ GPIO_PinModeSet(gpioPortD, 7, gpioModeWiredAndPullUpFilter, 1); GPIO_PinModeSet(gpioPortD, 6, gpioModeWiredAndPullUpFilter, 1); /* Enable pins at location 2 */ I2C0->ROUTE = (I2C_ROUTE_SDAPEN |I2C_ROUTE_SCLPEN |I2C_ROUTE_LOCATION_LOC1); //enable again BITBAND_Peripheral(&(I2C0->CTRL),_I2C_CTRL_EN_SHIFT,true); }
在以上代码中,并没有使能硬件I2C的中断,因此也不会调用I2C_Buslock_Process()函数。另外,针对该函数,目前也还没有做过功能验证,我只能通过短接SCL和SDA来测试。
I2C_Buslock_Process()原意是当I2C总线死锁的时候,控制I2C中的SCL时钟线产生9个时钟脉冲(针对8位数据的情况),这样I2C从设备就可以完成被挂起的读操作,从死锁状态中恢复过来。
在主函数中的调用方式如下:I2C_SentData(SLAVE_ADDRESS, PWR_MGMT_1, 0x00);
I2C_ReadData(Address, RegAddress+1, &L);
2 0
- EFM32 硬件I2C操作
- EFM32-笔记-IO操作
- 硬件I2C
- STM32--硬件I2C-2402
- STM32--硬件I2C-2402
- I2C总线硬件基础
- STM32F407的硬件I2C
- STM32 I2C硬件
- nRF52832之硬件I2C
- EFM32片内外设--LCD Bitband操作
- EFM32片内外设--RMU基本操作
- EFM32片内外设--WDT基本操作
- EFM32片内外设--VCMP 基本操作
- EFM32片内外设--RMU基本操作
- I2C操作
- I2C操作
- I2C操作
- 硬件总线接口系列-I2C
- java代码问题分析之静态分析工具(Klocwork Insight)
- 记性不如烂笔头29-java应用中的过滤器Filter(1)
- 彻底删除SQL Server 2005
- windows 服务的创建和部署
- Shell 函数
- EFM32 硬件I2C操作
- NameError: name 'commands' is not defined
- Linux多线程编程 - sleep 和 pthread_cond_timedwait
- cocos2d-x windows开发环境配置
- SQL Server 事务、异常和游标
- iOS基础控件的学习
- SQL基础(廿)--- 抑制重复
- 【LeetCode】Remove Nth Node From End of List
- 向正在运行的Linux应用程序注入代码