历史上的今天
今天是:2025年04月08日(星期二)
2019年04月08日 | STM32F103 Slave I2C配置
2019-04-08 来源:eefocus
才接触STM32开发,由于项目需求需要,需要linux系统与STM32通过I2C进行通讯,网上合适资料有限,花了不少时间,所以记录在此。
描述:Linux发送数据后,每隔10ms轮询stm32(应该做中断触发的,但由于硬件接口限制),只读一个字节判断是否有数据,如果有则读相应长度的内容。
自定义缓冲区格式:首字节为长度信息,后面是内容信息,如
uint8_t I2C_Buffer_Rx[128];//0:len 1...=>data
(1)I2C Slave初始化
void IIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB , ENABLE);
/* Configure I2C2 pins: SCL and SDA */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11; //10:SCL 11:SDA
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_APB1PeriphClockCmd (RCC_APB1Periph_I2C2, ENABLE);
I2C_DeInit(I2C2);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x10<<1;//temp addr
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 400000;
I2C_Init(I2C2, &I2C_InitStructure);
I2C_ITConfig(I2C2, I2C_IT_EVT|I2C_IT_BUF, ENABLE);
I2C_Cmd(I2C2,ENABLE);
}
(2)I2C中断配置
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
上述两条是基本操作,仔细看参数是没啥问题,最麻烦的是I2C状态,使用官方的问题很大,例如:
#define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */
而实还有0x20402的情况,类似情况太多了,经常冒出一个新状态,并且接收和停止可能合在一起。我开始使用case语句来判断状态的,待状态测试稳定后使用if来进行Bit位判断,目前比较稳定。见I2C中断处理。
(3)I2C中断处理
此地方核心是I2C状态处理,收发的数据格式类似串口操作,代码如下:
uint8_t I2C_Buffer_Rx[128];//0:len 1...=>data
static uint8_t I2C_Buffer_Tx[128];//0:len 1...=>data
void I2C2_EV_IRQHandler(void)
{
uint32_t I2CFlagStatus;
static uint8_t num = 0;
I2CFlagStatus = I2C_GetLastEvent(I2C2); // => (SR2<<16|SR1)
if ((I2CFlagStatus & 0x02) != 0){ //bit1:addr matched
if(I2CFlagStatus & 0x80) //bit7 Data register empty (transmitters)
{//read
num = 0;
I2C_SendData(I2C2, I2C_Buffer_Tx[num]);
}else{
num = 1;
I2C_Buffer_Tx[0] = 0;
I2C_Buffer_Rx[0] = 0;
}
}else if((I2CFlagStatus & 0x80) != 0){ // bit7 TxE -Data register empty (transmitters)
if((I2CFlagStatus & 0x04)==0){ //bit2 BTF (Byte transfer finished)
num++;
I2C_SendData(I2C2, I2C_Buffer_Tx[num]); //printf("I2C status:0x%xrn", I2CFlagStatus);
}
}else if((I2CFlagStatus & 0x40)&&(I2CFlagStatus & 0x10)){ //bit6(RxNE) + bit4(STOPF)
I2C_Buffer_Rx[num] = I2C_ReceiveData(I2C2); //g_debug_count1++;
num++;
I2C_Buffer_Rx[0] = num-1;
I2C2->CR1 |= 0x1000;//CR1_PEC_Set;
}else if((I2CFlagStatus & 0x40) != 0){ //bit6 RxNE -Data register not empty (receivers))
I2C_Buffer_Rx[num] = I2C_ReceiveData(I2C2);
num++;
}else if((I2CFlagStatus & 0x10) != 0){ //bit4 STOPF -Stop detection (slave mode)
I2C_Buffer_Rx[0] = num-1;
I2C2->CR1 |= 0x1000;//CR1_PEC_Set;
}else{
printf("I2C error status:0x%xrn", I2CFlagStatus);
}
I2C2->SR1=0;
I2C2->SR2=0;
}
(4)数据接收处理
我传输的数据长度是7到128字节之间。
void Recive_RXD_Deal(void)
{//I2C_Buffer_Rx 0:len 1->data
u8 i,len;
len = I2C_Buffer_Rx[0];
if(len)
{
/*printf("i2c recv len:%d:",len);
for(i=1; i<=len; i++)
printf(" %x ",I2C_Buffer_Rx[i]);
printf("endrn");*/
if(len < 7) return;
if( len != (I2C_Buffer_Rx[3]+1)) return;
if(I2C_Buffer_Rx[len-1] == (unsigned char )(Cheak_Sum(len-4, I2C_Buffer_Rx+3) &0xff))
{
UART2RXBuffer_Checked = &I2C_Buffer_Rx[1];
RXD_Deal_PROCESS();
}else{
printf("checksum error data[%d]=> ",len);
for(i=0; i<=len; i++) printf(" 0x%02x",I2C_Buffer_Rx[i]);
printf("endn");
}
I2C_Buffer_Rx[0]=0;
}
}
(5)数据发送接口:
void Raspberry_Send_Datas(unsigned char *data,uint16_t length)
{
uint8 i;
// printf("send data len[%d]:",length);
for(i=0; i { I2C_Buffer_Tx[i+1]=*(data+i); // printf("%x ",*(data+i)); } // printf("endrn"); I2C_Buffer_Tx[0] = length+1; } 应该就上面这些了。
史海拾趣
|
电路理论和实践之精深,远远不是几年时间就能全面掌握的。这几年自己在学习电路尤其是高频和天馈方面也走了不少弯路,君也是同路人,不妨在此谈谈——尤其是将来想做模拟和高频、天馈的同志们,也许看了本人的教训,以后不会走那么多弯路(觉得有道 ...… 查看全部问答> |
|
我准备在EVC4.0+oledb+sql ce2.0开发程序,在wince.net下运行。 CString str0; str0=\"select EmployeeID,LastName,FirstName \"; str0=str0+\"from Employees\"; &n ...… 查看全部问答> |
|
全新STM8S问世为8位微控制器的性能、可扩展性和价值树立新 意法半导体(ST)全新STM8S问世为8位微控制器的性能、可扩展性和价值树立新标杆利用STM8S的平台理念和先进架构技术,增强功能,缩短设计周期,提高灵活性中国,2009年3月4日 —— 意法半导体(纽约证券交易所代码:STM)今天宣布,针对 ...… 查看全部问答> |
|
晶闸管的触发方式有移相触发和过零触发两种。常用的触发电路与主回路之间由于有电的联系,易受电网电压的波动和电源波形畸变的影响,为解决同步问题,往往又使电路较为复杂。MOTOROLA公司生产的MOC3021-3081器件可以很好地解决这些问题。该器件用 ...… 查看全部问答> |




