RS485通讯实验
1.硬件:
STM32的串口管教加一个485芯片控制IO:
还需要一个USB 转485转换器,一端接485AB,USB口插PC上用串口助手查看数据。
注意点:以板子为核心,PC12置1为向外发送数据,PC12置0为向内接收数据。
2.代码,效果就是串口3发送5字节数据后收到同样5字节数据的返回:
rs485.h文件:
#ifndef RS485_RS485_H_
#define RS485_RS485_H_
#include "Sys.h"
u8 RS485_RX_CNT;
//接收缓存区
u8 RS485_RX_BUF[64]; //接收缓冲,最大64个字节.;
void RS485_Send_Data(u8 *buf,u8 len);
void RS485_Receive_Data(u8 *buf,u8 *len);
#endif /* RS485_RS485_H_ */
rs485.c文件:
#include "rs485.h"
#include "Uart.h"
volatile unsigned char RS485_REC_Flag = 0;
//接收缓存区
u8 RS485_RX_BUF[64]; //接收缓冲,最大64个字节.
//接收到的数据长度
u8 RS485_RX_CNT=0;
//RS485发送len个字节.
//buf:发送区首地址
//len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
void RS485_Send_Data(u8 *buf,u8 len)
{
u8 t;
GPIO_SetBits(GPIOC,GPIO_Pin_12);
for(t=0;t<len;t++) //循环发送数据
{
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
USART_SendData(USART3,buf[t]);
}
while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
RS485_RX_CNT=0;
GPIO_ResetBits(GPIOC,GPIO_Pin_12);
}
//RS485查询接收到的数据
//buf:接收缓存首地址
//len:读到的数据长度
void RS485_Receive_Data(u8 *buf,u8 *len)
{
u8 rxlen=RS485_RX_CNT;
u8 i=0;
u8 lenx = 5;
*len=0; //默认为0
delay_ms(100); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
if(rxlen==RS485_RX_CNT&&rxlen)//接收到了数据,且接收完成了
{
for(i=0;i<rxlen;i++)
{
buf[i]=RS485_RX_BUF[i];
}
RS485_Send_Data(buf,lenx);
*len=RS485_RX_CNT; //记录本次数据长度
RS485_RX_CNT=0; //清零
}
}
void USART3_IRQHandler(void)
{
u8 res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收到数据
{
res =USART_ReceiveData(USART3); //读取接收到的数据
if(RS485_RX_CNT<64)
{
RS485_RX_BUF[RS485_RX_CNT]=res; //记录接收到的值
RS485_RX_CNT++; //接收数据增加1
}
}
}
Uart.h文件:
#ifndef UART_UART_H_
#define UART_UART_H_
#include "Sys.h"
#define USART_REC_LEN 200 //定义最大接收字节数 200
u16 USART_RX_STA; //接收状态标记
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
void uart_init(u32 bound);
void uart3_init(u32 bound);
#endif /* UART_UART_H_ */
Uart.c文件:
#include "Uart.h"
void uart_init(u32 bound)
{
//USART 初始化设置
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = bound;//串口波特率
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(UART5, &USART_InitStructure); //初始化串口1
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(UART5, ENABLE); //使能串口1
}
void uart3_init(u32 bound)
{
//USART 初始化设置
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = bound;//串口波特率
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(USART3, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART3, ENABLE); //使能串口1
USART_ClearITPendingBit(USART3, USART_IT_TC);//清除中断TC位
}
Sys.h文件:
#ifndef SYS_SYS_H_
#define SYS_SYS_H_
#include <stdio.h>
#include <string.h>
#include "stm32f10x.h"
#define True (1)
#define False (0)
typedef uint32_t u32;///32位
void delay_init(void);
void RCC_Configuration(void);
void GPIO_RemapConfig(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void systemInit(void);
void delay_ms(u16 nms);
#endif /* SYS_SYS_H_ */
Sys.c文件:
#include "Sys.h"
#include "Uart.h"
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数,在ucos下,代表每个节拍的ms数
//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
}
void RCC_Configuration(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC, ENABLE); //使能USART1,GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOA.10
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//浮空输入
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOA.10
}
void GPIO_RemapConfig(void)
{
GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
}
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2
//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
void systemInit(void)
{
SystemInit();
delay_init();
RCC_Configuration(); // RCC配置
GPIO_Configuration(); // GPIO配置
GPIO_RemapConfig(); // GPIO重映射
NVIC_Configuration(); // NVIC配置
uart3_init(9600);
}
main.c文件:
#include "Sys.h"
#include "Uart.h"
#include "rs485.h"
void getSysClk(void)
{
RCC_ClocksTypeDef get_rcc_clock;
RCC_GetClocksFreq(&get_rcc_clock);
}
int main(void)
{
TimerFlagCounter = 0x00;
TimerFlag = False;
USART_RX_STA = 0;
RS485_RX_CNT = 0;
u8 rs485buf[5];
u8 key = 0x05;
systemInit();
while(1)
{
RS485_Receive_Data(rs485buf,&key);
}
return 0;
}