STM32的RS485通信

最新更新时间:2022-01-14来源: eefocus关键字:STM32  RS485通信 手机看文章 扫描二维码
随时随地手机看文章

1.简介

与CAN类似,RS-485是一种工业控制环境中常用的通讯块议,它具有抗干扰能力强、传输距离远的特点。RS-485通讯协议由RS-232协议改进而来,协议层不变,只是改进了物理层,因而保留了串口通讯协议应用简单的特点。

在这里插入图片描述

用的是SP3485芯片:

通信的时候,A端口连接另一个设备的A端口,B端口连接B端口,不是交叉相连。

最多能够连接128个设备,所以在某种情况下可以取代网络,RE引脚用来控制通讯数据的方向,要么进行接收,要么进行发送。

本质还是串口通信


RS485_RE为高电平的时候,DE为高电平有效,允许发送数据

RS485_RE为低电平的时候,RE为低电平有效,允许接收数据


所以当你要发送数据的时候 ,需要将与RE连接的引脚置为高电平、


2.编码

所以我们大致可以得到一个程序模板:


发送数据函数

void rs485_send(uint8_t *pbuf,uint32_t len)

{

//设置RS458为发送模式,将所连引脚设置高电平输出

PGout(2)=1;

//调用串口2的库函数发送数据

...

//延时100us

delay_us(100);

//设置RS485为接收模式

PGout(2)=0;


}

接收函数,使用中断接收

void USART2_IRQHandler(void)

{

uint8_t data=0;

if(USART2_GetITStatus(USART2,USART_IT_RXNE)!=RESET)

data = USART2_ReceiveData(USART2);


}


下面是演示代码,供参考


#include "stm32f4xx.h"

#include "stm32f4xx_gpio.h"

#include "stm32f4xx_rcc.h"

#include "stm32f4xx_usart.h"


//模式控制

#define RS485_TX_EN PGout(8) //485模式控制.0,接收;1,发送.

static GPIO_InitTypeDef  GPIO_InitStructure;

static USART_InitTypeDef USART_InitStructure;

static NVIC_InitTypeDef NVIC_InitStructure;    


void USART1_Init(uint32_t baud)

{

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //使能USART1时钟

 

//串口1对应引脚复用映射

GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1

GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1

//USART1端口配置

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10


//USART1 初始化设置

USART_InitStructure.USART_BaudRate = baud; //波特率设置

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式

USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位

USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式

USART_Init(USART1, &USART_InitStructure); //初始化串口1

USART_Cmd(USART1, ENABLE);  //使能串口1 

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启相关中断


//Usart1 NVIC 配置

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //串口1中断通道

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3

NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器

}



void USART1_WriteBytes(uint8_t *pbuf,uint32_t len)

{

uint32_t i =0;

for(i=0; i {

//发送数据

USART_SendData(USART1,*pbuf++);

while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);

}

}


//初始化IO 串口2

//baud:波特率   

void RS485_Init(uint32_t baud)

 


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //使能USART2时钟

//串口2引脚复用映射

GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA2复用为USART2

GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA3复用为USART2

//USART2    

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //GPIOA2与GPIOA3

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA2,PA3

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG,ENABLE); //使能GPIOA时钟

//PG8推挽输出,485模式控制  

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //GPIOG8

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出

GPIO_InitStructure.GPIO_PuPd  =  GPIO_PuPd_UP; //上拉

GPIO_Init(GPIOG,&GPIO_InitStructure); //初始化PG8


//USART2 初始化设置

USART_InitStructure.USART_BaudRate = baud; //波特率设置

USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式

USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位

USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式

USART_Init(USART2, &USART_InitStructure); //初始化串口2

USART_Cmd(USART2, ENABLE);  //使能串口 2

USART_ClearFlag(USART2, USART_FLAG_TC);


USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启接收中断


//Usart2 NVIC 配置

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //抢占优先级3

NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器

RS485_TX_EN=0; //默认为接收模式


}


//RS485发送len个字节.

//pbuf:发送区首地址

//len:发送的字节数

void RS485_Send_Data(uint8_t *pbuf,uint32_t len)

{

uint32_t i;


RS485_TX_EN=1; //设置为发送模式

for(i=0; i //循环发送数据

{

USART_SendData(USART2,pbuf[i]); //发送数据

while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);

}

delay_us(100);

RS485_TX_EN=0; //设置为接收模式


}


int main(void)

SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 

//设置中断优先级分组2

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

//串口1,波特率115200bps,开启接收中断

USART1_Init(115200);

//RS485初始化,115200bps

RS485_Init(115200);

while(1)

{


}

}



void USART1_IRQHandler(void)    //串口1中断服务程序

{

uint8_t d;


if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断

{

//接收数据

d = USART_ReceiveData(USART1);


RS485_Send_Data(&d,1);

 



void USART2_IRQHandler(void)

{

uint8_t d;

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//接收到数据

{  

d =USART_ReceiveData(USART2); //读取接收到的数据USART2->DR


USART1_WriteBytes(&d,1);

 

}

关键字:STM32  RS485通信 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic557780.html

上一篇:STM32F429--EXTI外部中断/事件控制器
下一篇:STM32模拟IIC通信

推荐阅读

STM32笔记——GPIO
GPIO简介GPIO是通用输出输入端口的简称,简单来说就是STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯、控制以及数据采集功能。GPIO的基本结构1、保护二极管与上下拉电阻当外部输入电压高于VDD的电压时,上方的保护二极管导通,当外部输入电压底于Vss的电压时,上方的保护二极管导通,防止不正常电压引入芯片导致芯片烧毁。2、P-MOS管和N-MOS管在输出模式部分,线路经过一个由"P-MOS"和"N-MOS"组成的结构,这个结构使其拥有"推挽输出"和"开漏输出"的功能。3、TTL肖特基触发器4、IO耐压STM32
发表于 2022-07-01
<font color='red'>STM32</font>笔记——GPIO
STM32笔记——外部中断的配置
一、选择对应芯片常规操作,这里我们选择F407ZGT6二、配置sys选择Serial Wire三、配置RCC选择高速外部时钟晶振,系统自动配置相应引脚。四、配置外部中断引脚通过查看开发板原理图,找出按键对应引脚五、设置外部中断引脚1、上升沿触发(外部中断触发引脚上的电平从低电平跳转到高电平)2、下降沿触发(外部中断触发引脚上的电平从高电平跳转到低电平)3、上下边沿均触发 (外部中断触发引脚上有电平变化)六、开启外部中断七、配置中断优先级八、配置时钟九、生成工程HAL库GPIO函数库讲解1、外部中断服务函数void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);功能:用于清除中断标志位实例:H
发表于 2022-07-01
<font color='red'>STM32</font>笔记——外部中断的配置
STM32笔记——外部中断
基本概念一、中断和异常1、中断——当需要出现时,CPU暂时停止当前程序的执行,转而执行处理新情况的程序和执行过程。2、异常——处理器要复位,不可屏蔽中断,存储故障,这些由内核产生的就叫做异常,也就是硬件异常。二、EXIT和NVICEXIT外部中断/事件控制器 外部中断/事件控制器包含多达 23 个用于产生事件/中断请求的边沿检测器。每根输入线都可单独进行配置,以选择类型(中断或事件)和相应的触发事件(上升沿触发、下降沿触发或边沿触发)。每根输入线还可单独屏蔽。挂起寄存器用于保持中断请求的状态线。外部中断框图:触发机制上升沿:数字电路中,数字电平从低电平(数字“0”)变为高电平(数字“1”)的那一瞬间(时刻)叫作上升沿。下降沿:
发表于 2022-07-01
<font color='red'>STM32</font>笔记——外部中断
STM32学习第一课:STM32 编程的C语言基础
刚开始看STM32的库函数,会有很多疑惑,例如指针怎么用,结构体跟指针怎么配合,例如函数的参数有什么要求,如何实时更新IO口的数据等。如果重新进行C语言的学习,那么要学很久才能够系统地认识。这里将比较容易想不起来的知识点进行简单的整理。1、#ifdef 和 #ifndef#ifdef 标识符A// 如果标识符A定义了,就编译程序段1,否则编译程序段2程序段1#else程序段2#endif#ifndef 的功能则与 #ifdef相反,是没有定义标识符A的时候编译程序段1。2、全局define在软件的选项中,有如此一栏,在上面填写的变量则表示在所有的文件中,上述的标识均被定义过。#ifdef STM32F10X_HD大容量芯片需要的一些
发表于 2022-07-01
STM32学习第二课:STM32c语言基础2
1.Typedeftypedef用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。typedef在MDK用得最多的就是定义结构体的类型别名和枚举类型了。如:typedef struct{ u16 seq_num; u16 len; u8 dev_id[GPRS_PRO_DEVICE_ID]; u16 command_id; u8 *pro_data;}gprs_pro_cmd_t;然后我们就可以直接使用gprs_pro_cmd_t定义一个结构体变量。2.结构体① 一般形式:Struct 结构体名 { 成员列表; }变量名列表;② 这样是声明后直接定义,也可以先声明,后定义;如:Struct 结构体名字 { 成员列表
发表于 2022-07-01
STM32学习第三课:STM32 c语言学习基础3(内存操作、指针、结构指针)
1.内存操作在对内存操作头疼的时候我发现了这篇神奇的文章,拜读之后豁然开朗心生崇拜数据指针在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具有的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:(1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;(2) 两个CPU之间以双端口RAM通信,CPU需要在双端口RAM的特定单元(称为mail box)书写内容以在对方CPU产生中断;(3) 读取在ROM或FLASH的特定单元所烧录的汉字和英文字模。
发表于 2022-07-01
<font color='red'>STM32</font>学习第三课:<font color='red'>STM32</font> c语言学习基础3(内存操作、指针、结构指针)

推荐帖子

51精通的情况下,再学STM32需要多长时间
51精通的情况下,再学STM32需要多长时间 51精通的情况下,再学STM32需要多长时间
深圳小花 单片机
菜地公告---菜农将开设STM32菜鸟实习栏目
为配合菜农玩一种新的ARM的心理,特此将开设STM32菜鸟实习栏目.在做菜鸟期间,菜农都会做一些"家庭作业"和倒塌STM32的心得体会.虽然逢菜农忙于做PIC24FJ菜鸟期间,但还是抽空学习学习最近的技术.也赶赶时髦,以不被时代抛弃~~~虽然还没接触过STM32,也没看数据手册,但菜农的首次倒塌STM32理论上已经成功~~~在做STM32菜鸟期间,俺将会继续倒塌~~~菜农HotPower@126.com2007.12.200:18于西安大雁塔村队部相关链接:htt
nov30th stm32/stm8
在msp430g2231中如何开启basic timer 的中断
我在g2231中的userguide中看到的IE1,即InterruptEnableRegister1,他控制的是Oscillatorfaultinterruptenable,这个是什么东西,还有要想开启g2231basictimer的中断该用什么语句呢? 在Fx42x中用IE2=BTIE就可以开中断在msp430g2231中如何开启basictimer的中断
gh1134537617 微控制器 MCU
EEWORLD大学堂----Altera 2014技术巡展(2)Stratix 10 FPGA简介
Altera2014技术巡展(2)Stratix10FPGA简介:http://training.eeworld.com.cn/course/2032Altera2014技术巡展(2)Stratix10FPGA简介EEWORLD大学堂----Altera2014技术巡展(2)Stratix10FPGA简介
chenyy FPGA/CPLD
并联谐振
并联谐振中为什么改变电容C,电感L值输出波形会发生变化,原理是什么!! 并联谐振
A001 模拟电子
最后一天!TI有奖直播|使用DLP®微型投影技术的IoT显示方案
直播主题 使用DLP®微型投影技术的IoT显示方案 直播时间 2022年6月22日(周三)上午10:00-11:30 内容简介 介绍如何利用DLP®微型投影技术实现IoT产品的差异化。超小型投影机让嵌入投影显示的IoT产品外观不再受限于实体面板,设计师可以自由发挥为嵌入投影显示的产品实现各种独特的造型。这种产品可以投影到任意表面来显示。本次线上会议将介绍主要功能,系统考量,评估模块以及第三方资源。 >&g
EEWORLD社区 TI技术论坛
小广播
实战 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2022 EEWORLD.com.cn, Inc. All rights reserved