欢迎光临散文网 会员登陆 & 注册

STM32 设置I2C从机模式DMA中断接收

2023-04-03 00:57 作者:我就是LYM  | 我要投稿

周末摆弄了一天,被各种垃圾文档啥的淹没不知所措,自己最后研究出来了之后不知道发哪,想来想去发B站专栏得了。(强烈需求专栏支持markdown)

需求是这样的:俺手里有一个STM32F407 开发板(以下简称STM32),还有一个树莓派PICO(以下简称树莓派),想试一下两者通过I2C进行数据对发。俺寻思把STM32作为从机,树莓派作为主机,使用树莓派每100ms发送消息给从机,从机接收。

硬件连线如下

硬件连接


树莓派代码如下(基于micropython)

注意地址需要和STM32的一致

STM32 CUBEMX生成器管脚配置如图

STM32管脚配置图(没截图到的都是没配置的)
I2C的参数配置
I2C中断打开event中断
配置I2C的DMA

【用来和上位机通信的UART配置,不需要的话可以不管】

这里实现的是烂大街的空闲中断接收任意长度的UART

UART配置
打开中断(用于实现任意长度接收)
配置UART的DMA

STM32代码部分:

包含stdio.h
定义接收用的相关变量
重定向printf到UART(不向上位机输出可以不定义)
主函数内代码

【重点】在stm32f4xx_it.c中

在DMA中断服务函数结束后进行后续处理
UART的可以放到前面

【附录】:在main.h中做如下的extern

方便在中断中去调用相关变量

运行结果:串口打印:

串口打印证明OK

树莓派代码源码如下:

from machine import I2C,Pin

from utime import sleep



i2c= I2C(0,sda=Pin(0),scl=Pin(1),freq=100000)


buf = b'this is i2c hello'



if __name__ == '__main__':

    while True:

        i2c.writeto(32,buf)

        print('send buf')

        sleep(0.1)


STM32重要代码块如下:

main.c内

/* USER CODE BEGIN Includes */

#include "stdio.h"

/* USER CODE END Includes */


/* USER CODE BEGIN PV */

uint8_t receive_num;

uint8_t i2c_receive_num;

uint8_t u1_rec_buf[MAX_BUF];

uint8_t i2c_rec_buf[MAX_BUF];

/* USER CODE END PV */

/* USER CODE BEGIN PFP */

#pragma import(__use_no_semihosting)             

            

struct __FILE {

int handle; 

}; 

FILE __stdout;       


void _sys_exit(int x){ 

x = x; 


int fputc(int ch, FILE* stream)

{

HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xFFFFF);

return ch;

}

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */

extern DMA_HandleTypeDef hdma_i2c1_rx;


/* USER CODE END 0 */

/* USER CODE BEGIN 2 */


__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

HAL_UART_Receive_DMA(&huart1,u1_rec_buf,MAX_BUF);


HAL_I2C_Slave_Receive_DMA(&hi2c1,i2c_rec_buf,MAX_BUF);

printf("ALL INIT OK\n");

printf("I2C1 WORKMODE %d\n",HAL_I2C_GetMode(&hi2c1));

  /* USER CODE END 2 */

main.h内

/* USER CODE BEGIN EC */

#define MAX_BUF 200

extern uint8_t u1_rec_buf[];

extern uint8_t receive_num;

extern uint8_t i2c_receive_num;

extern uint8_t i2c_rec_buf[];

/* USER CODE END EC */

stm32f4xx_it.c内

void DMA1_Stream0_IRQHandler(void)

{

  /* USER CODE BEGIN DMA1_Stream0_IRQn 0 */

  /* USER CODE END DMA1_Stream0_IRQn 0 */

  HAL_DMA_IRQHandler(&hdma_i2c1_rx);

  /* USER CODE BEGIN DMA1_Stream0_IRQn 1 */

i2c_receive_num = MAX_BUF-__HAL_DMA_GET_COUNTER(&hdma_i2c1_rx);

printf("Receive : %d\n",i2c_receive_num);

printf("%s\n",i2c_rec_buf);

HAL_I2C_Slave_Receive_DMA(&hi2c1,i2c_rec_buf,MAX_BUF);

  /* USER CODE END DMA1_Stream0_IRQn 1 */

}


void USART1_IRQHandler(void)

{

  /* USER CODE BEGIN USART1_IRQn 0 */

if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)==SET)   

{

__HAL_UART_CLEAR_IDLEFLAG(&huart1);                     

HAL_UART_DMAStop(&huart1); 

receive_num=MAX_BUF-__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);

HAL_UART_Receive_DMA(&huart1,u1_rec_buf,MAX_BUF);

}

  /* USER CODE END USART1_IRQn 0 */

  HAL_UART_IRQHandler(&huart1);

  /* USER CODE BEGIN USART1_IRQn 1 */


  /* USER CODE END USART1_IRQn 1 */

}



STM32 设置I2C从机模式DMA中断接收的评论 (共 条)

分享到微博请遵守国家法律