STM32学习笔记17—485通信实验
17.1 485协议概述
485是属于OSI模型物理层的电气标准,属于2线制,半双工,多点通信标准,485总线采用两根线路的电压差来传递信号,485两根线路名称为A和B,当线路A与线路B的电压差为+2~+6V时表示逻辑电平1,当线路A与线路B的电压差为-2~-6V时表示逻辑电平0,485与232协议都属于串口通信协议,都是采用转换芯片将USART接口电平转换为485电平或者232电平,485协议传输速率在10米时候可达35Mbps,在1200米是可达到100Kbps,最大支持总线挂载32个节点,如果采用特制的芯片可以达到400个节点。
485电气连接中,为了进行阻抗匹配,需要在两根线路中并联一个120Ω的电阻,一般是一个设备并联一个,所以485协议只是之前USART协议的另一种表现形式,通过之前掌握的USART配置,借助485转换芯片就可以完成485通信线路的搭建。
17.2 实验例程
采用STM32F103ZET6芯片的PA2(USART2_TXD)和PA3(USART2_RXD)和一个485转换芯片SP485来实现RS485通信。其中SP485引脚描述如下图所示。
(1)创建rs485.h文件,输入以下代码。 - /*********************************************************************************************************
- RS485 驱 动 文 件
- *********************************************************************************************************/
- #ifndef _RS485_H_
- #define _RS485_H_
- #include "sys.h"
- /*********************************************************************************************************
- 硬 件 端 口 定 义
- *********************************************************************************************************/
- #define RS485_EN PDout( 7 )
- /*********************************************************************************************************
- 数 据 结 构 定 义
- *********************************************************************************************************/
- typedef struct
- {
- u8 Buffer[ 255 ] ;
- u8 Len ;
- }Communication_Data;
- extern Communication_Data RS485_Data;
- /*********************************************************************************************************
- 函 数 列 表
- *********************************************************************************************************/
- void RS485_Init( u32 pclk1,u32 bound ) ; //RS485初始化
- void RS485_Send_Data( u8 *buf, u8 len ) ; //发送n个字节
- void RS485_Receive_Data( u8 *buf, u8 *len ) ; //接收n个字节
- #endif
复制代码
(2)创建rs485.c文件,输入以下代码。 - #include "rs485.h"
- #include "delay.h"
- Communication_Data RS485_Data;
- /***************************************************
- Name :USART2_IRQHandler
- Function :串口2中断服务函数
- Paramater :None
- Return :None
- ***************************************************/
- void USART2_IRQHandler()
- {
- //接收到数据
- if( USART2->SR&( 1<<5 ) )
- {
- RS485_Data.Buffer[ RS485_Data.Len ] = USART2->DR ; //记录接收到的值
- RS485_Data.Len ++ ; //接收数据增加1
- }
- }
- /***************************************************
- Name :RS485_Send_Data
- Function :接收n个字节
- Paramater :
- *buf:接收区首地址
- len:读取的字节数
- Return :None
- ***************************************************/
- void RS485_Receive_Data( u8 *buf, u8 *len )
- {
- u8 i, rxlen=RS485_Data.Len ;
- delay_ms( 10 ) ; //连续超过10ms没有接收到一个数据,则认为接收结束
- //接收到了数据,且接收完成了
- if( ( rxlen==RS485_Data.Len )&&( rxlen!=0 ) )
- {
- for( i=0; i<rxlen; i++ )
- buf[ i ] = RS485_Data.Buffer[ i ] ;
- *len = RS485_Data.Len ; //记录本次数据长度
- RS485_Data.Len = 0 ; //清零
- }
- }
- /***************************************************
- Name :RS485_Send_Data
- Function :发送n个字节
- Paramater :
- *buf:发送区首地址
- len:发送的字节数
- Return :None
- ***************************************************/
- void RS485_Send_Data( u8 *buf, u8 len )
- {
- u8 t ;
- RS485_EN = 1 ; //设置为发送模式
- //循环发送数据
- for( t=0; t<len; t++ )
- {
- while( ( USART2->SR&0x40 )==0 ) ;//等待发送结束
- USART2->DR = buf[ t ] ;
- }
- while( ( USART2->SR&0x40 )==0 ) ; //等待发送结束
- RS485_Data.Len = 0 ;
- RS485_EN = 0 ; //设置为接收模式
- }
- /***************************************************
- Name :RS485_Init
- Function :RS485初始化
- Paramater :
- pclk1:PCLK1时钟频率
- bound:波特率
- Return :None
- ***************************************************/
- void RS485_Init( u32 pclk1, u32 bound )
- {
- float temp ;
- u16 mantissa, fraction ;
- temp = ( float )( pclk1*1000000 )/( bound*16 ) ; //得到USARTDIV
- mantissa = temp ; //得到整数部分
- fraction = ( temp-mantissa )*16 ; //得到小数部分
- mantissa <<= 4 ;
- mantissa += fraction ;
- RCC->APB2ENR |= 1<<5 ; //使能PD口
- GPIOD->CRL &= 0x0FFFFFFF ;
- GPIOD->CRL |= 0x30000000 ;
- RCC->APB2ENR |= 1<<2 ; //使能PA口
- GPIOA->CRL &= 0xFFFF00FF ; //IO状态设置
- GPIOA->CRL |= 0x00008B00 ; //IO状态设置
- RCC->APB1ENR |= 1<<17 ; //使能串口时钟
- RCC->APB1RSTR |= 1<<17 ; //复位串口2
- RCC->APB1RSTR &= ~( 1<<17 ) ; //停止复位
- //波特率设置
- USART2->BRR = mantissa ; //波特率设置
- USART2->CR1 |= 0x200C ; //1位停止,无校验位
- USART2->CR1 |= 1<<8 ; //PE中断使能
- USART2->CR1 |= 1<<5 ; //接收缓冲区非空中断使能
- NVIC_Init( 3, 3, USART2_IRQn, 2 ) ; //组2
- RS485_EN = 0 ; //默认为接收模式
- }
复制代码
(3)创建1.c文件,输入以下代码。 - #include "sys.h"
- #include "delay.h"
- #include "usart1.h"
- #include "rs485.h"
- int main()
- {
- u8 len, datatemp[ 10 ] ;
- STM32_Clock_Init( 9 ) ; //STM32时钟初始化
- SysTick_Init( 72 ) ; //SysTick初始化
- USART1_Init( 72, 115200 ) ; //初始化串口1波特率115200
- RS485_Init( 36, 9600 ) ; //初始化RS485
- RS485_Send_Data( "RS485 Test", 10 ) ; //发送数据
- while( 1 )
- {
- RS485_Receive_Data( datatemp, &len ) ;
- delay_ms( 10 ) ;
- }
- }
复制代码
文章出处: 滑小稽笔记
|