STM32 設(shè)置I2C從機模式DMA中斷接收
周末擺弄了一天,被各種垃圾文檔啥的淹沒不知所措,自己最后研究出來了之后不知道發(fā)哪,想來想去發(fā)B站專欄得了。(強烈需求專欄支持markdown)
需求是這樣的:俺手里有一個STM32F407 開發(fā)板(以下簡稱STM32),還有一個樹莓派PICO(以下簡稱樹莓派),想試一下兩者通過I2C進行數(shù)據(jù)對發(fā)。俺尋思把STM32作為從機,樹莓派作為主機,使用樹莓派每100ms發(fā)送消息給從機,從機接收。
硬件連線如下

樹莓派代碼如下(基于micropython)

STM32 CUBEMX生成器管腳配置如圖





【用來和上位機通信的UART配置,不需要的話可以不管】
這里實現(xiàn)的是爛大街的空閑中斷接收任意長度的UART




STM32代碼部分:




【重點】在stm32f4xx_it.c中


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

運行結(jié)果:串口打印:


樹莓派代碼源碼如下:
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內(nèi)
/* 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內(nèi)
/* 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內(nèi)
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 */
}