1.采用485来进行数据通讯,串口采用的是DMA+空闲中断来接收数据,但始终无法进入中断!
2.采用串口通讯助手,发送数据可以正常接收到返回帧,证明器件没有问题
3.rs485.h
#ifndef __RS485_H_
#define __RS485_H_
#include "./SYSTEM/sys/sys.h"
#include "./BSP/PCF8574/pcf8574.h"
#include "./BSP/LED/led.h"
#define DMA_REC_LEN 50
#define USART_TX_PIN GPIO_PIN_2
#define USART_TX_PORT GPIOA
#define USART_RX_PIN GPIO_PIN_3
#define USART_RX_PORT GPIOA
#define RS485_RE_IO 6
void MY_RS485_Init(uint32_t bound);
void MY_RS485_DMA_Init(void);
void RS485_Mode(uint8_t mode);
void RS485_Send_Data(uint8_t *data,uint8_t len);
void HAL_UART_ReceiveIdle(UART_HandleTypeDef *huart);
void Copy_Data(uint8_t *buf,uint16_t len);
#endif
4.rs485.c
#include "./BSP/RS485/rs485.h"
#define UART2_DMA_RX 1
#define UART2_DMA_TX 0
#define CHECK_NONE_ONE_STOP 1
#define CHECK_NONE_TWO_STOP 0
#define CHECK_EVEN 0
#define CHECK_ODD 0
UART_HandleTypeDef USART2_RS485Handler;
DMA_HandleTypeDef USART2_DMAHandler;
uint8_t DMA_REC_BUF[DMA_REC_LEN]={0};
uint16_t RX_CNT = 0;
uint8_t rx_end_flag = 0;
uint8_t Data_BackUp[DMA_REC_LEN]={0};
uint16_t datalen_backup = 0;
void MY_RS485_Init(uint32_t bound){
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = USART_TX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(USART_TX_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = USART_RX_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(USART_RX_PORT, &GPIO_InitStruct);
USART2_RS485Handler.Instance = USART2;
USART2_RS485Handler.Init.BaudRate=bound;
USART2_RS485Handler.Init.HwFlowCtl =UART_HWCONTROL_NONE;
USART2_RS485Handler.Init.Mode =UART_MODE_TX_RX;
USART2_RS485Handler.Init.Parity =UART_PARITY_NONE;
USART2_RS485Handler.Init.WordLength =UART_WORDLENGTH_8B;
#if(CHECK_NONE_ONE_STOP== 1)
USART2_RS485Handler.Init.StopBits =UART_STOPBITS_1;
#endif
#if(CHECK_NONE_TWO_STOP== 1)
USART2_RS485Handler.Init.StopBits =UART_STOPBITS_2;
#endif
#if(CHECK_EVEN== 1)
USART2_RS485Handler.Init.Parity =UART_PARITY_EVEN;
#endif
#if(CHECK_ODD== 1)
USART2_RS485Handler.Init.Parity =UART_PARITY_ODD;
#endif
HAL_UART_Init(&USART2_RS485Handler);
USART2_RS485Handler.Instance->CR1 |= USART_CR1_RXNEIE;
RS485_Mode(0);
#if(UART2_DMA_RX== 1)
USART2_RS485Handler.Instance->CR1 |= USART_CR1_IDLEIE;
HAL_UART_Receive_DMA(&USART2_RS485Handler, DMA_REC_BUF, DMA_REC_LEN);
#endif
HAL_NVIC_SetPriority(USART2_IRQn, 2, 1);
HAL_NVIC_EnableIRQ(USART2_IRQn);
}
void MY_RS485_DMA_Init(void){
__HAL_RCC_DMA1_CLK_ENABLE();
USART2_DMAHandler.Instance =DMA1_Stream5;
USART2_DMAHandler.Init.Channel =DMA_CHANNEL_4;
USART2_DMAHandler.Init.Direction =DMA_PERIPH_TO_MEMORY;
USART2_DMAHandler.Init.PeriphInc =DMA_PINC_DISABLE;
USART2_DMAHandler.Init.MemInc =DMA_MINC_ENABLE;
USART2_DMAHandler.Init.PeriphDataAlignment =DMA_PDATAALIGN_BYTE;
USART2_DMAHandler.Init.MemDataAlignment =DMA_MDATAALIGN_BYTE;
USART2_DMAHandler.Init.Mode =DMA_CIRCULAR;
USART2_DMAHandler.Init.Priority =DMA_PRIORITY_MEDIUM;
USART2_DMAHandler.Init.FIFOMode =DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&USART2_DMAHandler);
__HAL_LINKDMA(&USART2_RS485Handler,hdmarx,USART2_DMAHandler);
__HAL_DMA_ENABLE(&USART2_DMAHandler);
HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);
}
void DMA1_Stream5_IRQHandler(void){
HAL_DMA_IRQHandler(&USART2_DMAHandler);
}
void USART2_IRQHandler(void){
LED1_TOGGLE();
HAL_UART_IRQHandler(&USART2_RS485Handler);
HAL_UART_ReceiveIdle(&USART2_RS485Handler);
while(HAL_UART_Receive_DMA(&USART2_RS485Handler, DMA_REC_BUF, DMA_REC_LEN) != HAL_OK);
}
void HAL_UART_ReceiveIdle(UART_HandleTypeDef *huart){
if(huart->Instance == USART2){
#if(UART2_DMA_RX== 1)
if((__HAL_UART_GET_FLAG(&USART2_RS485Handler, UART_FLAG_IDLE)) != RESET){
__HAL_DMA_DISABLE(&USART2_DMAHandler);
RX_CNT = DMA_REC_LEN - __HAL_DMA_GET_COUNTER(&USART2_DMAHandler);
Copy_Data(DMA_REC_BUF,RX_CNT);
__HAL_UART_CLEAR_FLAG(&USART2_RS485Handler, UART_FLAG_IDLE);
__HAL_DMA_ENABLE(&USART2_DMAHandler);
rx_end_flag = 1;
}
#endif
}
}
void Copy_Data(uint8_t *buf,uint16_t len){
uint16_t i;
datalen_backup = len;
for(i = 0; i < len; i++){
Data_BackUp[i] = buf[i];
}
}
void RS485_Send_Data(uint8_t *data,uint8_t len){
RS485_Mode(1);
while(__HAL_UART_GET_FLAG(&USART2_RS485Handler,UART_FLAG_TC) == RESET);
HAL_UART_Transmit(&USART2_RS485Handler,data, len, 1000);
while(__HAL_UART_GET_FLAG(&USART2_RS485Handler,UART_FLAG_TC) == RESET);
RX_CNT = 0;
RS485_Mode(0);
}
void RS485_Mode(uint8_t mode){
PCF8574_Write_Bit(RS485_RE_IO, mode);
}
5.STM32F429与温度传感器进行通讯,采用的为MODBUS通讯协议
#ifndef __RS_WS_N018_H_
#define __RS_WS_N018_H_
#include"./SYSTEM/sys/sys.h"
#include"./SYSTEM/delay/delay.h"
#include"./SYSTEM/usart/usart.h"
#include"./BSP/RS485/rs485.h"
#include"string.h"
#define DEV_ADDR 0x01
#define FUN_CODE 0x03
#define HUMI_ADDR 0x0000
#define TEMP_ADDR 0x0001
uint16_t CRC_16_HEX(uint8_t *Buf, uint8_t CRC_CNT);
voidN018_Send_HTCommand(void);
uint8_t N018_Scan(float *temp,float *humi);
#endif
#include "./BSP/RS_WS_N018/rs_ws_n018.h"
extern uint8_t Data_BackUp[DMA_REC_LEN];
extern uint8_t rx_end_flag;
uint8_t RS485_Send_Buf[10] = {0};
uint8_t CRC_BUF[2] ={0};
uint16_t CRC_16_HEX(uint8_t *Buf, uint8_t CRC_CNT)
{
unsigned long CRC_Temp;
unsigned char i,j;
CRC_Temp = 0xffff;
for (i=0; i<CRC_CNT; i++) {
CRC_Temp ^= Buf[i];
for (j=0; j<8; j++) {
if (CRC_Temp & 0x01)
CRC_Temp = (CRC_Temp >>1 ) ^ 0xA001;
else
CRC_Temp = CRC_Temp >> 1;
}
}
return(CRC_Temp>>8|CRC_Temp<<8);
}
void N018_Send_HTCommand(void){
uint8_t addr_buf[2] ={DEV_ADDR,FUN_CODE};
RS485_Send_Buf[0] = addr_buf[0];
RS485_Send_Buf[1] = addr_buf[1];
RS485_Send_Buf[2] = (uint8_t)HUMI_ADDR>>8;
RS485_Send_Buf[3] = (uint8_t)HUMI_ADDR&0xFF;
RS485_Send_Buf[4] = 0x00;
RS485_Send_Buf[5] = 0x02;
CRC_BUF[0] = (CRC_16_HEX(RS485_Send_Buf, 6)>>8);
CRC_BUF[1] = CRC_16_HEX(RS485_Send_Buf, 6)&0xFF;
RS485_Send_Buf[6] = CRC_BUF[0];
RS485_Send_Buf[7] = CRC_BUF[1];
RS485_Send_Data(RS485_Send_Buf,8);
}
uint8_t N018_Scan(float *temp,float *humi){
uint8_t ret = 1;
uint16_t temperature = 0, humidity = 0;
RS485_Send_Buf[0] = 0X01;
RS485_Send_Buf[1] = 0X03;
RS485_Send_Buf[2] = 0X00;
RS485_Send_Buf[3] = 0X00;
RS485_Send_Buf[4] = 0x00;
RS485_Send_Buf[5] = 0x02;
RS485_Send_Buf[6] = 0XC4;
RS485_Send_Buf[7] = 0X0B;
RS485_Send_Data(RS485_Send_Buf,8);
printf("send successfully\r\n");
while(rx_end_flag == 0);
printf("receive successfully\r\n");
if(Data_BackUp[0]==RS485_Send_Buf[0]&&Data_BackUp[1]==RS485_Send_Buf[1]){
CRC_BUF[0] = (CRC_16_HEX(Data_BackUp, 7)>>8);
CRC_BUF[1] = CRC_16_HEX(Data_BackUp, 7)&0xFF;
if(CRC_BUF[0]==Data_BackUp[7]&&CRC_BUF[1]==Data_BackUp[8]){
humidity = Data_BackUp[3]<<8|Data_BackUp[4];
printf("humi:%d\r\n",humidity);
*humi = humidity % 10;
if(Data_BackUp[5]&0x80)
temperature = ~(Data_BackUp[5]<<8|Data_BackUp[6])+1;
else
temperature = Data_BackUp[5]<<8|Data_BackUp[6];
*temp = temperature % 10;
ret = 0;
}
}
printf("receive successfully\r\n");
return ret;
}