当前位置:网站首页>采用中微BATG135实现IIC数据/指令交互
采用中微BATG135实现IIC数据/指令交互
2022-07-04 06:19:00 【喜欢吃火锅的泪】
本例程是一次项目中使用到IIC实现3台中微直接的数据交互,而中微给出的IIC例程偏向简单,实现中遇到很多问题,要真正实现IIC,需要进行改写。
首先需要进行中微作为从机的初始化:
void IICA0_Init(void)
{
CGC->PER0 |= CGC_PER0_IICA0EN_Msk; /* enables input clock supply */
IICA->IICCTL00 = _00_IICA_OPERATION_STOP; /* stop operation */
INTC_DisableIRQ(IICA_IRQn); /* disable INTIICA interrupt flag */
INTC_ClearPendingIRQ(IICA_IRQn); /* clear INTIICA interrupt flag */#ifdef IICA_STANDARD_MODE /* Max rate: 100Kbps */
IICA->IICCTL01 = _00_IICA_OPERATE_STANDARD; /* operates in standard mode */
IICA->IICWL0 = _4B_IICA_LOW_WIDTH;
IICA->IICWH0 = _53_IICA_HIGH_WIDTH;
#endif
#ifdef IICA_FAST_MODE /* Max rate: 400Kbps */
IICA->IICCTL01 = _08_IICA_OPERATE_FAST; /* operates in fast mode */
IICA->IICCTL01 |= _04_IICA_FILTER_ON; /* filter on */
IICA->IICWL0 = _14_IICA_LOW_WIDTH;
IICA->IICWH0 = _12_IICA_HIGH_WIDTH;
#endif
IICA->IICCTL01 |= _01_IICA_FCLK_2_SELECTED;
IICA->SVA0 = _98_IICA0_SLAVEADDRESS;
IICA->IICF0 |= _02_IICA_WITHOUT_DETECTION; /* enable generation of a start condition without detecting a stop
condition */
IICA->IICF0 |= _01_IICA_RESERVATION_DISABLE; /* disable communication reservation */
IICA->IICCTL00 |= _08_IICA_INTERRUPT_REQUEST_NINTH; /* interrupt request is generated at the ninth clock's falling edge */
IICA->IICCTL00 |= _00_IICA_ACKOWNLEDGMENT_DISABLE; /* enable acknowledgment */
IICA->IICCTL00 |= _80_IICA_OPERATION_ENABLE; /* enable operation */
IICA->IICCTL00 |= _40_IICA_OPERATION_STANDBY; /* this exits from the current communications and sets standby mode */
INTC_EnableIRQ(IICA_IRQn); /* enable INTIICA interrupt flag *//* Set SCLA0, SDAA0 pin */
SCLA0_PORT_SETTING();
SDAA0_PORT_SETTING();
}
其中:可根据中微的GPIO口进行IIC管脚映射
#define SCLA0_PORT_SETTING() do{ \
PORT->SCLA0PCFG = 0x13; /* allocate SCLA0 to P30 */ \
PORT->P3 &= ~(1 << 0); /* P30 output low level */ \
PORT->PM3 &= ~(1 << 0); /* P30 is N-ch open-drain output mode */ \
PORT->PMC3 &= ~(1 << 0); /* P30 digital function */ \
}while(0)/* ToDo: You can allocate the SDA00 to any desired pins with SDA00PCFG register */
#define SDAA0_PORT_SETTING() do{ \
PORT->SDAA0PCFG = 0x17; /* allocate SDAA0 to P50 */ \
PORT->P5 &= ~(1 << 0); /* P50 output low level */ \
PORT->PM5 &= ~(1 << 0); /* P50 is used as SDAA0 inout */ \
PORT->PMC5 &= ~(1 << 0); /* P50 digital function */ \
}while(0)
接下来是中微作为从机,实现数据的收发:
void IIC_Rec_Fuction(void)
{
static uint8_t times = 0;
static uint16_t interval = 0;
uint8_t csc = 0;
if (0 == times)
{
times = 1;
g_iica0_rx_len = 200;
g_iica0_rx_cnt = 0U;
g_iica0_rx_end = 0;
g_iica0_slave_status_flag = 0U;
IICA->IICA0 = SLVADDR_98U; /* slave address */
interval = gMillisecondTick;
}
if (1 == times)
{
if (((gMillisecondTick - interval) & 0xFFFF) > 10) //10ms
{
if ((g_iica0_rx_end == 1) && (RxBuffer2[0] == 0x55) && (RxBuffer2[1] == 0xAA) && (RxBuffer2[2] != 0x00))
{
for(uint16_t i = 0; i < (RxBuffer2[2] + 1);i++ )
{
csc ^= RxBuffer2[i];
}
if(csc == RxBuffer2[RxBuffer2[2] + 1])
{
Sys_Data.CmdData = (RxBuffer2[4]<<8) + RxBuffer2[5]; /*获取功能指令*/
memcpy(Sys_Data.Rec_Data,RxBuffer2,sizeof(RxBuffer2)); /*获取接收数据*/
//Sys_Data.Rec_Data为结构体数组:200个字节uint8_t Rec_Data[200]; /*接收数组*/,到此处代表接收的数据没有问题可进入
/*IIC接收函数处理中*/
Rev_Process_Fuction();
Send_Process_Connect_Upload(); /*IIC发送数据线程*/
g_iica0_rx_len = 200;
g_iica0_rx_cnt = 0U;
g_iica0_rx_end = 0;
g_iica0_slave_status_flag = 0U;
IICA->IICA0 = SLVADDR_98U; /* slave address */
}
}
interval = gMillisecondTick;
}
}else
{
g_iica0_rx_len = 200;
g_iica0_rx_cnt = 0U;
g_iica0_rx_end = 0;
g_iica0_slave_status_flag = 0U;
IICA->IICA0 = SLVADDR_98U; /* slave address */
}
}
其中:需要注意的是,要记得修改中微官方给的中断函数:
uint8_t RxBuffer2[200]; /*接收数组*/
uint16_t RxCounter2 = 0; /*接收计数*//***********************************************************************************************************************
* Function Name: iica0_slavehandler
* @brief This function is IICA0 slave handler.
* @param None
* @return None
***********************************************************************************************************************/
static void iica0_slavehandler(void)
{
/* Control for stop condition */
if (IICA->IICS0 & IICA_IICS0_SPD_Msk)
{
/* Get stop condition */
IICA->IICCTL00 &= ~IICA_IICCTL00_SPIE_Msk; /* SPIE0 = 0: disable */
if(g_iica0_slave_status_flag & _80_IICA_ADDRESS_COMPLETE)
{
if (g_iica0_slave_status_flag & 0x04U) /* send flag */
{
iica0_callback_slave_sendend();
}
if (g_iica0_slave_status_flag & 0x02U) /* receive flag */
{
iica0_callback_slave_receiveend();
}
}
g_iica0_slave_status_flag = 1U;
}
else
{
if ((g_iica0_slave_status_flag & _80_IICA_ADDRESS_COMPLETE) == 0U)
{
if (IICA->IICS0 & IICA_IICS0_COI_Msk)
{
IICA->IICCTL00 |= IICA_IICCTL00_SPIE_Msk; /* SPIE0 = 1: enable */
g_iica0_slave_status_flag = _80_IICA_ADDRESS_COMPLETE;if (IICA->IICS0 & IICA_IICS0_TRC_Msk) /* TRC0 == 1 */
{
IICA->IICCTL00 |= IICA_IICCTL00_WTIM_Msk; /* WTIM0 = 1: interrupt request is generated at the ninth clock's falling edge */if (g_iica0_tx_cnt > 0U)
{
IICA->IICA0 = *gp_iica0_tx_address;
gp_iica0_tx_address++;
g_iica0_tx_cnt--;
}
else
{
iica0_callback_slave_sendend();
IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk; /* WREL0 = 1U: cancel wait */
}
}
else
{
IICA->IICCTL00 |= IICA_IICCTL00_ACKE_Msk; /* ACKE0 = 1U: enable acknowledgment */
IICA->IICCTL00 &= ~IICA_IICCTL00_WTIM_Msk; /* WTIM0 = 0U: interrupt request is generated at the eighth clock's falling edge */
IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk; /* WREL0 = 1U: cancel wait */
}
}
else
{
iica0_callback_slave_error(MD_ERROR);
}
}
else
{
if (IICA->IICS0 & IICA_IICS0_TRC_Msk) /* TRC0 == 1 */
{
g_iica0_slave_status_flag |= 4U; /* send flag */
if ((0U == (IICA->IICS0 & IICA_IICS0_ACKD_Msk)) && (g_iica0_tx_cnt != 0U))
{
iica0_callback_slave_error(MD_NACK);
}
else
{
if (g_iica0_tx_cnt > 0U)
{
IICA->IICA0 = *gp_iica0_tx_address;
gp_iica0_tx_address++;
g_iica0_tx_cnt--;
}
else
{
iica0_callback_slave_sendend();
IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk; /* WREL0 = 1U: cancel wait */
}
}
}
else
{
g_iica0_slave_status_flag |= 2U; /* receive flag */
if (g_iica0_rx_cnt < g_iica0_rx_len)
{
RxBuffer2[g_iica0_rx_cnt] = IICA->IICA0;
g_iica0_rx_cnt++;if (g_iica0_rx_cnt == g_iica0_rx_len)
{
IICA->IICCTL00 |= IICA_IICCTL00_WTIM_Msk; /* WTIM0 = 1: interrupt request is generated at the ninth clock's falling edge */
IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk; /* WREL0 = 1U: cancel wait */
iica0_callback_slave_receiveend();
}
else
{
IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk; /* WREL0 = 1U: cancel wait */
}
}
else
{
IICA->IICCTL00 |= IICA_IICCTL00_WREL_Msk; /* WREL0 = 1U: cancel wait */
}
}
}
}
}
/*
*********************************************************************************
* 函 数 名:Send_Process_Connect_Upload
* 功能说明:发送数据给蓝牙MCU
* 形 参:void
* 返 回 值:void
*********************************************************************************
*/
void Send_Process_Connect_Upload(void)
{
uint16_t value_size = 0;
//uint16_t i = 0;
//uint8_t tmpbuf[10]={0};
static uint8_t value[200] = {0};
/* 判断串口发送是否立即执行*/
if((Sys_Data.Com_Stas & COM_SEND_RDY) !=COM_SEND_RDY)
{
return;
}
/* 串口组包存值Value*/
// value_size = SendPacekData(Sys_Data.SendBuf,Sys_Data.SendLen,value);
IICA0_SlaveSend(SLVADDR_98U,value,value_size);
while(g_iica0_tx_end == 0);
#if 0
/*发送数据*/
printf_log("\r\n send_process :");
for(i=0;i<(value_size);i++)
{
memset(tmpbuf,0,10);
u8_T_array(value[i],tmpbuf);
printf_log((const char *)tmpbuf);
printf_log(" ");
}
printf_log("\r\n value_size = %d",value_size);
#endif
//Sys_Data.Com_Stas = 0; /*指令状态复位*/
// Sys_Data.CmdData = 0; /*指令复位*/
// Sys_Data.SendLen = 0; /*数据长度为0*/
// memset(Sys_Data.CmdPara,0,sizeof(Sys_Data.CmdPara)); /*命令数据包复位*/
}
边栏推荐
- How does apscheduler set tasks not to be concurrent (that is, execute the next task after the first one)?
- QT 获取随机颜色值设置label背景色 代码
- 如何展开Collapse 的所有折叠面板
- Invalid revision: 3.18.1-g262b901-dirty
- 《ClickHouse原理解析与应用实践》读书笔记(4)
- js arguments参数使用和详解
- LayoutManager布局管理器:FlowLayout、BorderLayout、GridLayout、GridBagLayout、CardLayout、BoxLayout
- QT QTableWidget 表格列置顶需求的思路和代码
- How to implement lazy loading in El select (with search function)
- 【无标题】
猜你喜欢
AWT介绍
QT get random color value and set label background color code
Appium基础 — APPium安装(二)
Experience weekly report no. 102 (July 4, 2022)
雲原生——上雲必讀之SSH篇(常用於遠程登錄雲服務器)
注释与注解
JSON Web Token----JWT和傳統session登錄認證對比
After the festival, a large number of people change careers. Is it still time to be 30? Listen to the experience of the past people
js arguments参数使用和详解
Arcpy uses the updatelayer function to change the symbol system of the layer
随机推荐
Configure cross compilation tool chain and environment variables
ES6 模块化
Stc8h development (XII): I2C drive AT24C08, at24c32 series EEPROM storage
HMS v1.0 appointment. PHP editid parameter SQL injection vulnerability (cve-2022-25491)
QT 获取随机颜色值设置label背景色 代码
如何避免 JVM 内存泄漏?
Fast power (template)
Lightroom import picture gray / Black rectangular multi display
JS get the attribute values nested in the object
Leetcode question brushing record | 206_ Reverse linked list
Notes and notes
gslb(global server load balance)技术的一点理解
Detectron:训练自己的数据集——将自己的数据格式转换成COCO格式
[March 3, 2019] MAC starts redis
微信小程序使用rich-text中图片宽度超出问题
MySQL learning notes 3 - JDBC
雲原生——上雲必讀之SSH篇(常用於遠程登錄雲服務器)
How to implement cross domain requests
How to implement lazy loading in El select (with search function)
对List进行排序工具类,可以对字符串排序