[STM32F4] STM32F4与树莓片通讯

[复制链接]
 楼主| 八月十五 发表于 2025-5-19 16:09 | 显示全部楼层 |阅读模式
本帖最后由 八月十五 于 2025-5-19 16:14 编辑

STM32F4与树莓派(Raspberry Pi)的通讯可以通过多种接口实现,常见的包括UART串口、SPII2C等。

1. UART串口通讯
特点:  
- 简单易用,适合调试和低速数据传输。  
- 树莓派和STM32F4均支持UART接口。  
实现步骤:  
1. 硬件连接:  
   - 树莓派的UART引脚(如GPIO14/TXDGPIO15/RXD)与STM32F4UART引脚(如PA9/TXPA10/RX)交叉连接。  
   - 确保两端的GND连接在一起。
1.png
2. 树莓派配置:  
   - 启用UART接口:  
   
  1. sudo raspi-config

     选择 `Interfacing Options > Serial > No`(禁用登录shell)和 `Yes`(启用硬件串口)。  
   - 重启树莓派。  
3. STM32F4配置:  
   - 使用STM32CubeMX配置UART外设(如USART1),设置波特率(如115200)、数据位、停止位等。  
   - 生成代码后,在用户代码中实现数据收发逻辑。  
4. 代码示例:  
   - 树莓派(Python):  
   
  1. import serial
  2. import time

  3. # 配置串口
  4. ser = serial.Serial(
  5.     port='/dev/ttyAMA0',  # 树莓派的串口设备文件
  6.     baudrate=115200,  # 波特率
  7.     bytesize=serial.EIGHTBITS,  # 数据位
  8.     parity=serial.PARITY_NONE,  # 无校验位
  9.     stopbits=serial.STOPBITS_ONE  # 停止位
  10. )

  11. try:
  12.     while True:
  13.         # 发送数据
  14.         send_data = 'Hello, STM32!'
  15.         ser.write(send_data.encode())
  16.         print(f'Sent: {send_data}')

  17.         # 接收数据
  18.         if ser.in_waiting > 0:
  19.             receive_data = ser.readline().decode().strip()
  20.             print(f'Received: {receive_data}')

  21.         time.sleep(1)

  22. except KeyboardInterrupt:
  23.     print('Communication stopped by user.')
  24. finally:
  25.     ser.close()


   - STM32F4:  
   
  1. #include "main.h"
  2. #include "usart.h"
  3. #include "gpio.h"

  4. uint8_t rx_data;

  5. void SystemClock_Config(void);

  6. int main(void)
  7. {
  8.   HAL_Init();
  9.   SystemClock_Config();
  10.   MX_GPIO_Init();
  11.   MX_USART1_UART_Init();

  12.   while (1)
  13.   {
  14.     // 接收数据
  15.     if (HAL_UART_Receive(&huart1, &rx_data, 1, 100) == HAL_OK)
  16.     {
  17.       // 回显接收到的数据
  18.       HAL_UART_Transmit(&huart1, &rx_data, 1, 100);
  19.     }
  20.   }
  21. }

  22. void SystemClock_Config(void)
  23. {
  24.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  25.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  26.   /** Initializes the RCC Oscillators according to the specified parameters
  27.   * in the RCC_OscInitTypeDef structure.
  28.   */
  29.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  30.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  31.   RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  32.   RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  33.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  34.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  35.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  36.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  37.   {
  38.     Error_Handler();
  39.   }
  40.   /** Initializes the CPU, AHB and APB buses clocks
  41.   */
  42.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
  43.                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  44.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  45.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  46.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  47.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  48.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  49.   {
  50.     Error_Handler();
  51.   }
  52. }

2. SPI通讯
特点:  
- 高速全双工通讯,适合需要较高带宽的应用。  
- 树莓派作为SPI主机,STM32F4作为从机。  
实现步骤:  
1. 硬件连接:  
   - 树莓派的SPI引脚(MOSIMISOSCLKCE0)与STM32F4SPI引脚(如PA7/MOSIPA6/MISOPA5/SCKPA4/CS)连接。  
2. 树莓派配置:  
   - 启用SPI接口:  
   
  1. sudo raspi-config

     选择 `Interfacing Options > SPI > Yes`。  
3. STM32F4配置:  
   - 使用STM32CubeMX配置SPI外设(如SPI1),设置为从机模式。  
4. 代码示例:  
   - 树莓派(Python,使用spidev库):  
   
  1. import spidev
  2. spi = spidev.SpiDev()
  3. spi.open(0, 0)  # 打开SPI总线0,设备0
  4. spi.max_speed_hz = 1000000  # 设置时钟频率
  5. response = spi.xfer2([0x01, 0x00, 0x00, 0x00])  # 发送并接收数据
  6. print(response)

   - STM32F4:  
   
  1. <pre style="overflow-wrap: initial; background: rgb(248, 248, 250); border-radius: 4px; font-size: 0.9em; overflow: auto; padding: calc(0.888889em); word-break: initial; color: rgb(25, 27, 31);"><code class="language-text" style="background-color: inherit; border-radius: 0px; font-family: Menlo, Monaco, Consolas, &quot;Andale Mono&quot;, &quot;lucida console&quot;, &quot;Courier New&quot;, monospace; font-size: inherit;">
  2. void SPI1_Init()
  3. {
  4.     GPIO_InitTypeDef GPIO_InitStructure;
  5.     SPI_InitTypeDef SPI_InitStructure;

  6.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);

  7.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  11.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  12.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  13.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  14.     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  15.     SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  16.     SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  17.     SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  18.     SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  19.     SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  20.     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
  21.     SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  22.     SPI_Init(SPI1, &SPI_InitStructure);

  23.     SPI_Cmd(SPI1, ENABLE);
  24. }

  25. void SPI1_SendData(uint8_t data)
  26. {
  27.     while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
  28.     SPI_I2S_SendData(SPI1, data);
  29. }

  30. uint8_t SPI1_ReceiveData()
  31. {
  32.     while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
  33.     return SPI_I2S_ReceiveData(SPI1);
  34. }</code></pre>


3. I2C通讯
特点:  
- 多主多从架构,适合连接多个设备。  
- 树莓派作为I2C主机,STM32F4作为从机。  
实现步骤:  
1. 硬件连接:  
   - 树莓派的I2C引脚(SDASCL)与STM32F4I2C引脚(如PB9/SDAPB8/SCL)连接。  
2. 树莓派配置:  
   - 启用I2C接口:  
     ```bash
     sudo raspi-config
     ```
     选择 `Interfacing Options > I2C > Yes`。  
3. STM32F4配置:  
   - 使用STM32CubeMX配置I2C外设(如I2C1),设置为从机模式,并设置唯一设备地址。  
4. 代码示例:  
   - 树莓派(Python,使用smbus库):  
   
  1. import smbus
  2. bus = smbus.SMBus(1)  # 使用I2C总线1
  3. bus.write_byte(0x48, 0x01)  # 向地址0x48的设备写入数据
  4. data = bus.read_byte(0x48)  # 从地址0x48的设备读取数据
  5. print(data)

   - STM32F4:  
  1. <pre style="overflow-wrap: initial; background: rgb(248, 248, 250); border-radius: 4px; font-size: 0.9em; overflow: auto; padding: calc(0.888889em); word-break: initial; color: rgb(25, 27, 31);"><code class="language-text" style="background-color: inherit; border-radius: 0px; font-family: Menlo, Monaco, Consolas, &quot;Andale Mono&quot;, &quot;lucida console&quot;, &quot;Courier New&quot;, monospace; font-size: inherit;">void I2C1_Init()
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     I2C_InitTypeDef I2C_InitStructure;

  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  6.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

  7.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.     GPIO_Init(GPIOB, &GPIO_InitStructure);

  11.     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
  12.     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
  13.     I2C_InitStructure.I2C_OwnAddress1 = 0x00;
  14.     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
  15.     I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  16.     I2C_InitStructure.I2C_ClockSpeed = 100000;

  17.     I2C_Init(I2C1, &I2C_InitStructure);

  18.     I2C_Cmd(I2C1, ENABLE);
  19. }

  20. void I2C1_WriteData(uint8_t slave_address, uint8_t *data, uint16_t size)
  21. {
  22.     while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

  23.     I2C_GenerateSTART(I2C1, ENABLE);
  24.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

  25.     I2C_Send7bitAddress(I2C1, slave_address, I2C_Direction_Transmitter);
  26.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  27.     while (size--)
  28.     {
  29.         I2C_SendData(I2C1, *data++);
  30.         while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  31.     }

  32.     I2C_GenerateSTOP(I2C1, ENABLE);
  33. }

  34. void I2C1_ReadData(uint8_t slave_address, uint8_t *data, uint16_t size)
  35. {
  36.     while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

  37.     I2C_GenerateSTART(I2C1, ENABLE);
  38.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

  39.     I2C_Send7bitAddress(I2C1, slave_address, I2C_Direction_Receiver);
  40.     while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

  41.     while (size)
  42.     {
  43.         if (size == 1)
  44.         {
  45.             I2C_AcknowledgeConfig(I2C1, DISABLE);
  46.             I2C_GenerateSTOP(I2C1, ENABLE);
  47.         }

  48.         while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
  49.         *data++ = I2C_ReceiveData(I2C1);
  50.         size--;
  51.     }

  52.     I2C_AcknowledgeConfig(I2C1, ENABLE);
  53. }</code></pre>

4. 其他通讯方式
- USB通讯:  
  - STM32F4可以通过USB-OTG接口模拟为虚拟串口(CDC)或HID设备,与树莓派通过USB线直接通讯。  
- 以太网/Wi-Fi:  
  - 树莓派和STM32F4均可通过以太网或Wi-Fi模块(如ESP8266)实现TCP/IP通讯,适合需要长距离或复杂网络协议的场景。  

选择建议
   简单调试:使用UART串口。  
  高速数据传输:使用SPI。  
  多设备连接:使用I2C。  
   复杂网络应用:使用以太网或Wi-Fi。  

注意事项
1. 电平匹配:  
   - 树莓派的GPIO3.3V电平,STM32F4通常也为3.3V电平,无需电平转换。  
   - 如果使用5V设备,需使用电平转换模块。  
2. 供电问题:  
   - 确保树莓派和STM32F4的供电稳定,避免因电流不足导致通讯异常。  
3. 调试工具:  
   - 使用逻辑分析仪或示波器检查信号波形,确保通讯正常。  
通过以上方法,可以灵活实现STM32F4与树莓派之间的通讯,满足不同应用场景的需求。

4y1b3 发表于 2025-5-31 23:52 | 显示全部楼层
串口设备在不同树莓派版本可能是 /dev/ttyAMA0 或 /dev/serial0,可以通过 ls -l /dev 确认。

小迷糊仙 发表于 2025-6-3 22:24 | 显示全部楼层
新人学习
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

6

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部