“线程: 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);
}
}