完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
今年才接触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); 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); 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; } 应该就上面这些了。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1786 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1622 浏览 1 评论
1089 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
730 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1680 浏览 2 评论
1942浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
739浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
576浏览 3评论
599浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
561浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 19:24 , Processed in 0.863697 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号