STM32使用485接口通讯
简单来说,485通信,实质还是串口通信。通过电平转换芯片,将TTL电平转换成485电平,即可使用485接口通信。
串口
串口是一种接口标准,只是物理层的一个标准。没有规定接口插件电缆以及使用的协议。
典型的串行通讯标准是RS232, RS485, RS422等,他们定义了电压,阻抗等,但不对软件协议给予定义。
串口通过电平转换电路,可以将串口电平(TTL)转换成485电平、232电平等。
RS485特点
- 接口电平低
- 逻辑“1”两线电压差为+(2~6)V;逻辑“0”两线电压差为-(2~6)V。
- 传输速度高
- 10米时,传输速度可达35Mbps
- 1200米时,传输速度可达100Kbps
- 抗干扰能力强
- 使用平衡驱动器和差分接收器组合,抗共模干扰能力强,
- 传输距离远,支持多节点
- RS485总线最长可以传输1200m以上(速率<=100Kbps)
- 一般支持32个节点,特定芯片支持128个,256,甚至400个节点
- 此处采用的芯片是ADM2483,可以支持256个节点
- RS485接口连接形式
- 点对点 A-A B-B
- 线性
- 总线型
- 不可是星型,环形
- 常见接口
- 接收输入端
- 发送输出端
- 接收使能信号,低电平有效
- 发送使能信号,高电平有效
- 由于半双工,常将 和 连在一起,由MCU某个引脚控制。但本人使用的电路板具有收发自动切换电路(TX连到三极管上拉下拉,具体实现可以参考 https://blog.csdn.net/wangguchao/article/details/80200402 其中的5.3自动切换电路)
RS485通信注意
- 对于MCU来说,485仅仅是使用电平转换芯片将TTL电平,转成485电平。即要使用485传输,本质上还是串口传输。
- 两个485通信,其技术指标应该是相同的,否则不能通信。
- 波特率
- 数据长度
- 停止位
- 校验位
- 硬件流控制
- 收发模式
相关代码
- 端口初始化与中断设置
/*
函数名称: RS485_Bus_Init(void)
输入: 无
输出: 无
功能: 设置485所在串口的端口与中断
注意: 此处使用的是串口5,U5TX->PC12,U5RX->PD2
使用了宏定义,请注意将宏定义内容添加到.h文件中
*/
void RS485_Bus_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5,ENABLE);
//PC12->U5TX
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//PD2->U5RX
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5,ENABLE);//复位串口5
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5,DISABLE);//停止复位
USART_InitStructure.USART_BaudRate = RS485_BUS_BOUND;//波特率设置
USART_InitStructure.USART_WordLength = RS485_BUS_WORDLENGTH;//8位数据长度
USART_InitStructure.USART_StopBits = RS485_BUS_STOPBITS;//一个停止位
USART_InitStructure.USART_Parity = RS485_BUS_PARITY;///奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = RS485_BUS_FLOWCTRL;//无硬件数据流控制
USART_InitStructure.USART_Mode = RS485_BUS_MODE;//收发模式
USART_Init(UART5, &USART_InitStructure); //初始化串口
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn; //使能串口2中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级2级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
USART_ITConfig(UART5,USART_IT_RXNE,ENABLE);
}
- 中断服务函数
/*
函数名称: UART5_IRQHandler(void)
输入: 无
输出: 无
功能: 串口接收非空中断,串口接收数据,存在串口缓存buf中
注意: 无
*/
void UART5_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(UART5,USART_IT_RXNE) != RESET)
{
res = USART_ReceiveData(UART5);
if(RS485_BUS_RXCNT<64)
{
RS485_BUS_RXBUF[RS485_BUS_RXCNT]=res;
RS485_BUS_RXCNT++;
}
}
}
- 发送数据
/*
函数名称: RS485_BUS_SendData(u8 *buf, u8 len)
输入: u8 *buf 发送数据的数组
u8 *len 发送数据的长度
输出: 无
功能: 将本地数据通过串口发送出去
注意: 无
*/
void RS485_BUS_SendData(u8 *buf, u8 len)
{
u8 t;
for(t=0;t<len;t++)
{
while(USART_GetFlagStatus(UART5,USART_FLAG_TC)==RESET);
USART_SendData(UART5,buf[t]);
}
while(USART_GetFlagStatus(UART5,USART_FLAG_TC)==RESET);
RS485_BUS_RXCNT = 0;
}
- 接收数据
/*
函数名称: RS485_BUS_ReceiveData(u8 *buf,u8 *len)
输入: u8 *buf 存放接收数据的数组
u8 *len 存放接收数据的长度
输出: 上述指针传递
功能: 从串口缓存中接收数据到本地缓存
注意: 串口缓存最大只能64个字节
*/
void RS485_BUS_ReceiveData(u8 *buf,u8 *len)
{
u8 rxlen=RS485_BUS_RXCNT;
u8 i=0;
*len=0;
delay_ms(10);
if((rxlen==RS485_BUS_RXCNT)&&rxlen) //接收到了数据且接收完成
{
for(i=0;i<rxlen;i++)
{
buf[i]=RS485_BUS_RXBUF[i];
}
*len=RS485_BUS_RXCNT;
RS485_BUS_RXCNT=0;
}
}
- rs485.h
#define RS485_BUS_BOUND 9600
#define RS485_BUS_WORDLENGTH USART_WordLength_8b
//USART_WordLength_8b
//USART_WordLength_9b
#define RS485_BUS_STOPBITS USART_StopBits_1
//USART_StopBits_1
//USART_StopBits_0_5
//USART_StopBits_2
//USART_StopBits_1_5
#define RS485_BUS_PARITY USART_Parity_No
//USART_Parity_No
//USART_Parity_Even
//USART_Parity_Odd
#define RS485_BUS_FLOWCTRL USART_HardwareFlowControl_None
//USART_HardwareFlowControl_None
//USART_HardwareFlowControl_RTS
//USART_HardwareFlowControl_CTS
//USART_HardwareFlowControl_RTS_CTS
#define RS485_BUS_MODE USART_Mode_Rx|USART_Mode_Tx
//USART_Mode_Rx
//USART_Mode_Tx
总结
485通信和串口通信,对MCU来说是没有差异的。了解串口通信,通过电平转换芯片即可以完成485通信。
第一篇文章,多有错漏还请各位斧正。