“线程: LP5562, 测试”中讨论的其它部件
msp430fr2676硬件 I2C 首次执行接收一个额外的字节数据。
MCLK 16M,SMCLK 16M,I2C 速率400K, 从设备 lp5562,IDE CCS10
第一个
其他
i2c.h
//***************************************************************************** // //! ucb1_i2c.h - \b EUSCI_B1_I2C驱动程序头文件 //! //! @author CVZTS //! @date 2022-01-27 //! @version V100R001SP0001 // //***************************************************************************** #ifndef __DRIVER_UCB1_I2C_H__ #define __DRIVER_UCB1_I2C_H__ #ifdef __cplusplus extern "C" { #endif /* * =============================== 返回码定义 ================================= */ #define UCB1_I2C_SUCCESS (0) // 执行成功 #define UCB1_I2C_ERROR_BUSY (-1) // 数据总线忙 #define UCB1_I2C_ERROR_NAK (-2) // 设备未应答 /* * ================================ 全局定义 ================================== */ #define UCB1_I2C_CS_SMCLK (0) // I2C模块时钟源SMCLK #define UCB1_I2C_CS_ACLK (1) // I2C模块时钟源ACLK #define UCB1_I2C_RATE_100K (0) // I2C接口速率100KBps #define UCB1_I2C_RATE_400K (1) // I2C接口速率400KBps /* * ================================== API ==================================== */ //***************************************************************************** // //! \brief 初始化UCB1_I2C接口 //! //! \param[in] clkSrc I2C模块时钟源 //! - \b UCB1_I2C_CS_SMCLK //! - \b UCB1_I2C_CS_ACLK //! //! \param[in] clock I2C模块时钟源频率(Hz) //! //! \param[in] rate I2C接口速率 //! - \b UCB1_I2C_RATE_100K //! - \b UCB1_I2C_RATE_400K //! //! \return none //! \note none // //***************************************************************************** extern void drv_InitUCB1I2C(uint8_t clkSrc, uint32_t clock, uint8_t rate); //***************************************************************************** // //! \brief 设置设备地址 //! //! \param[in] addr 设备地址 //! //! \return none //! \note none // //***************************************************************************** extern void drv_UCB1I2CSetSlaveAddress(uint8_t addr); //***************************************************************************** // //! \brief 获取设备地址 //! //! \param none //! //! \return 设备地址 //! //! \note none // //***************************************************************************** extern uint8_t drv_UCB1I2CGetSlaveAddress(void); //***************************************************************************** // //! \brief 设置I2C最大错误重试次数 //! //! \param[in] retNum 最大重试次数(0-255) //! //! \return none //! \note none // //***************************************************************************** extern void drv_UCB1I2CSetRetriesNumber(uint8_t retNum); //***************************************************************************** // //! \brief 获取I2C最大错误重试次数 //! //! \param none //! //! \return 最大错误重试次数 //! //! \note none // //***************************************************************************** extern uint8_t drv_UCB1I2CGetRetriesNumber(void); //***************************************************************************** // //! \brief I2C读取多字节数据 //! //! \param[in] regAddr 起始寄存器地址 //! \param[in] dataPtr 保存已读取数据的指针 //! \param[in] size 读取数据多大小 //! //! \return 如果成功返回 \b UCB1_I2C_SUCCESS //! 否则返回 \b UCB1_I2C_ERROR_BUSY or \b UCB1_I2C_ERROR_NAK //! \note none // //***************************************************************************** extern int16_t drv_UCB1I2CReadMultiByte(uint8_t regAddr, uint8_t *dataPtr, uint16_t size); #ifdef __cplusplus } #endif #endif // __DRIVER_UCB1_I2C_H__
I2C.c.
//***************************************************************************** // //! ucb1_i2c.c - \b EUSCI_B1_I2C驱动程序源文件 //! //! @author CVZTS //! @date 2022-02-05 //! @version V100R001SP0001 // //***************************************************************************** /* * =============================== 头文件引入 ================================= */ #include "board.h" #include "ucb1_i2c.h" #include "uartprint/uartprint.h" /* * ================================ 全局定义 ================================== */ #define I2C_RETRIES_MAX (3) // 最大重试次数 /* * ================================ 数据结构 ================================== */ // UCB1_I2C 信息存储块数据结构 typedef struct t_UCB1I2CBlock { uint8_t retriesNumber; // 最大重试次数 } UCB1I2CBlock; /* * ================================ 全局变量 ================================== */ // UCB1_I2C模块时钟源列表 static uint8_t g_clockSourceList[2] = { [UCB1_I2C_CS_SMCLK] = EUSCI_B_I2C_CLOCKSOURCE_SMCLK, [UCB1_I2C_CS_ACLK] = EUSCI_B_I2C_CLOCKSOURCE_ACLK }; // UCB1_I2C接口速率列表 static uint32_t g_rateList[2] = { [UCB1_I2C_RATE_100K] = EUSCI_B_I2C_SET_DATA_RATE_100KBPS, [UCB1_I2C_RATE_400K] = EUSCI_B_I2C_SET_DATA_RATE_400KBPS }; // UCB1_I2C 信息存储块 static UCB1I2CBlock g_block = {0}; /* * ================================ 内部函数 ================================== */ /* * ================================== API ==================================== */ //***************************************************************************** // //! \brief 初始化UCB1_I2C接口 //! //! \param[in] clkSrc I2C模块时钟源 //! - \b UCB1_I2C_CS_SMCLK //! - \b UCB1_I2C_CS_ACLK //! //! \param[in] clock I2C模块时钟源频率(Hz) //! //! \param[in] rate I2C接口速率 //! - \b UCB1_I2C_RATE_100K //! - \b UCB1_I2C_RATE_400K //! //! \return none //! \note none // //***************************************************************************** void drv_InitUCB1I2C(uint8_t clkSrc, uint32_t clock, uint8_t rate) { // // 设置I2C错误最大重试次数 // g_block.retriesNumber = I2C_RETRIES_MAX; // // EUSCIA重新映射源选择 // SYSCFG3 |= USCIB1RMP; // // EUSCI_B1_I2C 初始化 // EUSCI_B_I2C_initMasterParam _param = {0}; _param.selectClockSource = g_clockSourceList[clkSrc]; _param.i2cClk = clock; _param.dataRate = g_rateList[rate]; _param.byteCounterThreshold = 0; _param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; MAP_EUSCI_B_I2C_initMaster(EUSCI_B1_BASE, &_param); // // 设置I2C为传输模式 // MAP_EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE); // // 启用I2C模块 // EUSCI_B_I2C_enable(EUSCI_B1_BASE); // // 清除I2C中断标志 // MAP_EUSCI_B_I2C_clearInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_RECEIVE_INTERRUPT0); } //***************************************************************************** // //! \brief 设置设备地址 //! //! \param[in] addr 设备地址 //! //! \return none //! \note none // //***************************************************************************** void drv_UCB1I2CSetSlaveAddress(uint8_t addr) { EUSCI_B_I2C_setSlaveAddress(EUSCI_B1_BASE, addr); } //***************************************************************************** // //! \brief 获取设备地址 //! //! \param none //! //! \return 设备地址 //! //! \note none // //***************************************************************************** uint8_t drv_UCB1I2CGetSlaveAddress(void) { return (HWREG16(EUSCI_B1_BASE + OFS_UCBxI2CSA)); } //***************************************************************************** // //! \brief 设置I2C最大错误重试次数 //! //! \param[in] retNum 最大重试次数(0-255) //! //! \return none //! \note none // //***************************************************************************** void drv_UCB1I2CSetRetriesNumber(uint8_t retNum) { g_block.retriesNumber = retNum; } //***************************************************************************** // //! \brief 获取I2C最大错误重试次数 //! //! \param none //! //! \return 最大错误重试次数 //! //! \note none // //***************************************************************************** uint8_t drv_UCB1I2CGetRetriesNumber(void) { return (g_block.retriesNumber); } //***************************************************************************** // //! \brief I2C读取多字节数据 //! //! \param[in] regAddr 起始寄存器地址 //! \param[in] dataPtr 保存已读取数据的指针 //! \param[in] size 读取数据多大小 //! //! \return 如果成功返回 \b UCB1_I2C_SUCCESS //! 否则返回 \b UCB1_I2C_ERROR_BUSY or \b UCB1_I2C_ERROR_NAK //! \note none // //***************************************************************************** int16_t drv_UCB1I2CReadMultiByte(uint8_t regAddr, uint8_t *dataPtr, uint16_t size) { // //! 等待总线空闲 //! 如果累计重试次数等于最大错误重试次数 //! 返回 \b UCB1_I2C_ERROR_BUSY // uint8_t _retNum = 0; while(MAP_EUSCI_B_I2C_isBusBusy(EUSCI_B1_BASE)) { _retNum++; if (_retNum == g_block.retriesNumber) { return (UCB1_I2C_ERROR_BUSY); } } // // 设置I2C为传输模式 // MAP_EUSCI_B_I2C_setMode(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_MODE); // // 发送写入数据开始信号 // MAP_EUSCI_B_I2C_masterSendStart(EUSCI_B1_BASE); // // 等待开始信号 // while(EUSCI_B_I2C_SENDING_START == MAP_EUSCI_B_I2C_masterIsStartSent(EUSCI_B1_BASE)); // // 如果设备未应答 // if (MAP_EUSCI_B_I2C_getInterruptStatus(EUSCI_B1_BASE, EUSCI_B_I2C_NAK_INTERRUPT)) { // // 发送停止信号 // MAP_EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B1_BASE); // // 等待停止信号发送 // while (EUSCI_B_I2C_SENDING_STOP == MAP_EUSCI_B_I2C_masterIsStopSent(EUSCI_B1_BASE)); // // 清除中断标志 // MAP_EUSCI_B_I2C_clearInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0 + EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_BYTE_COUNTER_INTERRUPT); // // 返回错误代码 // return (UCB1_I2C_ERROR_NAK); } // // 发送寄存器地址 // MAP_EUSCI_B_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, regAddr); // // 清除Tx中断标志 // MAP_EUSCI_B_I2C_clearInterrupt(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0); // // 发送接收起始信号 // MAP_EUSCI_B_I2C_masterReceiveStart(EUSCI_B1_BASE); // // 等待开始信号生成 // while(EUSCI_B_I2C_SENDING_START == MAP_EUSCI_B_I2C_masterIsStartSent(EUSCI_B1_BASE)); for (uint16_t i = 0; i < size; i++) { // // 接收数据 // dataPtr[i] = MAP_EUSCI_B_I2C_masterReceiveSingle(EUSCI_B1_BASE); } // // 发送停止信号 // MAP_EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B1_BASE); // // 轮询等待停止信号发送完成 // while (EUSCI_B_I2C_SENDING_STOP == MAP_EUSCI_B_I2C_masterIsStopSent(EUSCI_B1_BASE)); return (UCB1_I2C_SUCCESS); }
请致电
void main(void) { drv_InitUCB1I2C(UCB1_I2C_CS_SMCLK, CS_getSMCLK(), UCB1_I2C_RATE_400K); drv_UCB1I2CSetSlaveAddress(0x30); uint8_t _buff[10]; while (1) { drv_UCB1I2CReadMultiByte(0x00, _buff, 10); __delay_cycles(50000); } }