搜索
查看: 1370|回复: 0

[分享] STM32学习笔记17—485通信实验

[复制链接]

该用户从未签到

193

主题

194

帖子

0

蝴蝶豆

金牌会员

最后登录
2021-3-12
发表于 2021-3-10 13:31:26 | 显示全部楼层 |阅读模式
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引脚描述如下图所示。

4.1.png

4.2.png

4.3.png

(1)创建rs485.h文件,输入以下代码。
  1. /*********************************************************************************************************
  2.                   RS485    驱    动    文    件
  3. *********************************************************************************************************/
  4. #ifndef _RS485_H_
  5. #define _RS485_H_

  6. #include "sys.h"
  7. /*********************************************************************************************************
  8.                 硬    件    端    口    定    义
  9. *********************************************************************************************************/
  10. #define RS485_EN  PDout( 7 )
  11. /*********************************************************************************************************
  12.                 数    据    结    构    定    义
  13. *********************************************************************************************************/
  14. typedef struct
  15. {
  16.   u8 Buffer[ 255 ] ;
  17.   u8 Len ;
  18. }Communication_Data;
  19. extern Communication_Data RS485_Data;
  20. /*********************************************************************************************************
  21.                     函    数    列    表
  22. *********************************************************************************************************/
  23. void RS485_Init( u32 pclk1,u32 bound ) ;                                //RS485初始化
  24. void RS485_Send_Data( u8 *buf, u8 len ) ;                                //发送n个字节
  25. void RS485_Receive_Data( u8 *buf, u8 *len ) ;                              //接收n个字节

  26. #endif
复制代码

(2)创建rs485.c文件,输入以下代码。
  1. #include "rs485.h"
  2. #include "delay.h"

  3. Communication_Data RS485_Data;
  4. /***************************************************
  5. Name    :USART2_IRQHandler
  6. Function  :串口2中断服务函数
  7. Paramater  :None
  8. Return    :None
  9. ***************************************************/
  10. void USART2_IRQHandler()
  11. {
  12.   //接收到数据
  13.   if( USART2->SR&( 1<<5 ) )
  14.   {
  15.     RS485_Data.Buffer[ RS485_Data.Len ] = USART2->DR ;                        //记录接收到的值
  16.     RS485_Data.Len ++ ;                                        //接收数据增加1
  17.   }
  18. }
  19. /***************************************************
  20. Name    :RS485_Send_Data
  21. Function  :接收n个字节
  22. Paramater  :
  23.       *buf:接收区首地址
  24.       len:读取的字节数
  25. Return    :None
  26. ***************************************************/
  27. void RS485_Receive_Data( u8 *buf, u8 *len )
  28. {
  29.   u8 i, rxlen=RS485_Data.Len ;
  30.   delay_ms( 10 ) ;                                          //连续超过10ms没有接收到一个数据,则认为接收结束
  31.   //接收到了数据,且接收完成了
  32.   if( ( rxlen==RS485_Data.Len )&&( rxlen!=0 ) )
  33.   {
  34.     for( i=0; i<rxlen; i++ )
  35.       buf[ i ] = RS485_Data.Buffer[ i ] ;
  36.     *len = RS485_Data.Len ;                                      //记录本次数据长度
  37.     RS485_Data.Len = 0 ;                                      //清零
  38.   }
  39. }
  40. /***************************************************
  41. Name    :RS485_Send_Data
  42. Function  :发送n个字节
  43. Paramater  :
  44.       *buf:发送区首地址
  45.       len:发送的字节数
  46. Return    :None
  47. ***************************************************/
  48. void RS485_Send_Data( u8 *buf, u8 len )
  49. {
  50.   u8 t ;
  51.   RS485_EN = 1 ;                                            //设置为发送模式
  52.   //循环发送数据
  53.     for( t=0; t<len; t++ )
  54.   {
  55.     while( ( USART2->SR&0x40 )==0 ) ;//等待发送结束
  56.     USART2->DR = buf[ t ] ;
  57.   }   
  58.   while( ( USART2->SR&0x40 )==0 ) ;                                  //等待发送结束  
  59.   RS485_Data.Len = 0 ;
  60.   RS485_EN = 0 ;                                            //设置为接收模式
  61. }
  62. /***************************************************
  63. Name    :RS485_Init
  64. Function  :RS485初始化
  65. Paramater  :
  66.       pclk1:PCLK1时钟频率
  67.       bound:波特率
  68. Return    :None
  69. ***************************************************/
  70. void RS485_Init( u32 pclk1, u32 bound )
  71. {
  72.   float temp ;
  73.   u16 mantissa, fraction ;
  74.   temp = ( float )( pclk1*1000000 )/( bound*16 ) ;                          //得到USARTDIV
  75.   mantissa = temp ;                                          //得到整数部分
  76.   fraction = ( temp-mantissa )*16 ; //得到小数部分   
  77.     mantissa <<= 4 ;
  78.   mantissa += fraction ;
  79.   RCC->APB2ENR |= 1<<5 ;                                        //使能PD口
  80.    GPIOD->CRL &= 0x0FFFFFFF ;
  81.   GPIOD->CRL |= 0x30000000 ;

  82.   RCC->APB2ENR |= 1<<2 ;                                        //使能PA口
  83.   GPIOA->CRL &= 0xFFFF00FF ;                                      //IO状态设置
  84.   GPIOA->CRL |= 0x00008B00 ;                                      //IO状态设置
  85.   RCC->APB1ENR |= 1<<17 ;                                        //使能串口时钟
  86.   RCC->APB1RSTR |= 1<<17 ;                                      //复位串口2
  87.   RCC->APB1RSTR &= ~( 1<<17 ) ;                                    //停止复位
  88.   //波特率设置
  89.    USART2->BRR = mantissa ;                                      //波特率设置
  90.   USART2->CR1 |= 0x200C ;                                        //1位停止,无校验位
  91.   USART2->CR1 |= 1<<8 ;                                        //PE中断使能
  92.   USART2->CR1 |= 1<<5 ;                                        //接收缓冲区非空中断使能
  93.   NVIC_Init( 3, 3, USART2_IRQn, 2 ) ;                                  //组2
  94.   RS485_EN = 0 ;                                            //默认为接收模式
  95. }
复制代码

(3)创建1.c文件,输入以下代码。
  1. #include "sys.h"
  2. #include "delay.h"
  3. #include "usart1.h"
  4. #include "rs485.h"

  5. int main()
  6. {
  7.   u8 len, datatemp[ 10 ] ;
  8.   STM32_Clock_Init( 9 ) ;                                        //STM32时钟初始化
  9.   SysTick_Init( 72 ) ;                                        //SysTick初始化
  10.   USART1_Init( 72, 115200 ) ;                                      //初始化串口1波特率115200
  11.   RS485_Init( 36, 9600 ) ;                                      //初始化RS485
  12.   RS485_Send_Data( "RS485 Test", 10 ) ;                                //发送数据
  13.   while( 1 )
  14.   {
  15.     RS485_Receive_Data( datatemp, &len ) ;
  16.     delay_ms( 10 ) ;
  17.   }
  18. }
复制代码

文章出处: 滑小稽笔

回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-4-25 07:59 , Processed in 1.169101 second(s), 32 queries .

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表