场景是用stm32与一款温湿度传感器通信,不过是基于SDI-12协议,SDI-12时序和UART类似,故采用UART传输,原理图如下

其中DIR_OUT_SDI是一个IO引脚,控制UART_TX_SDI是否使能,U10是三态门IC,即拉低DIR_OUT_SDI使能stm32输出,拉高DIR_OUT_SDI失能输出,串口配置8位数据位,偶校验,1位停止位,1200波特率。
下面给出发送一个激活命令的示例:
- #define SDI_BREAK_TIME 13
- #define SDI_BREAK_QUIET_TIME 20
-
- //@brief 发送确认激活命令
- //@param addr 传感器地址 ascii码 低7位有效
- void sdi12SendAckActive(uint8_t addr)
- {
- uint8_t cmd[]={'0'+addr,'!'};
- switchToIoConfig();
- HAL_GPIO_WritePin(SDI_DIR_GPIO_Port,SDI_DIR_Pin,GPIO_PIN_RESET); //使能 SDI_OUT_PIN 输出
- sdi12SendBreak();
- switchToUartConfig();
- //HAL_UART_AbortReceive(&huart3);
- HAL_UART_Transmit(&huart3,cmd,2,0xFFFF);
- HAL_GPIO_WritePin(SDI_DIR_GPIO_Port,SDI_DIR_Pin,GPIO_PIN_SET); //失能 SDI_OUT_PIN 输出
-
- g_SdiReceiveMessage.receiveFlag=0;
- g_SdiReceiveMessage.messageTop =0;
- HAL_UART_Receive_IT(&huart3, g_SdiReceiveMessage.message, 1);
- return;
- }
-
- //@brief 将tx引脚配置为输出模式,作输出唤醒信号使用
- void switchToIoConfig()
- {
- GPIO_InitTypeDef GPIO_InitStruct={0};
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(SDI_OUT_PORT, SDI_OUT_PIN, GPIO_PIN_SET);
-
- /*Configure GPIO pin : SPI_DIR_Pin */
- GPIO_InitStruct.Pin = SDI_OUT_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(SDI_OUT_PORT, &GPIO_InitStruct);
- return;
- }
-
- //@brief 发送唤醒信号
- void sdi12SendBreak()
- {
- HAL_GPIO_WritePin(SDI_OUT_PORT,SDI_OUT_PIN,GPIO_PIN_RESET);
- HAL_Delay(SDI_BREAK_TIME);
- HAL_GPIO_WritePin(SDI_OUT_PORT,SDI_OUT_PIN,GPIO_PIN_SET);
- HAL_Delay(SDI_BREAK_QUIET_TIME);
- }
-
- //@brief 将tx引脚配置为复用模式,作串口输出使用
- void switchToUartConfig()
- {
- GPIO_InitTypeDef GPIO_InitStruct={0};
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(SDI_OUT_PORT, SDI_OUT_PIN, GPIO_PIN_SET);
-
- GPIO_InitStruct.Pin = SDI_OUT_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
- HAL_GPIO_Init(SDI_OUT_PORT, &GPIO_InitStruct);
- return;
- }
示波器测试得到传感器的应答信号如下:第一个是唤醒信号,拉高电平13毫秒,之后保持20毫秒低电平,第二个数据帧是激活信号,即ascii码: "0!",第三个是传感器的应答信号:"0\r\n"
