中级会员
 
- 积分
- 309
- 金钱
- 309
- 注册时间
- 2016-5-20
- 在线时间
- 45 小时
|
10金钱
//不用总线空闲功能,就能准确的接收数据,用了接收到的数据就会多起来,求解,谢谢
//附上串口助手监控到的数据图片
//头文件
#ifndef __MODBUS_H
#define __MODBUS_H
#include "sys.h"
void RS485_Init(void);
void RS485_Send_Data(void);
void RS485_Receive_Data(void);
FlagStatus RCV_SEND_Mod(u8 rcv_complete, u8 send_complete);
extern u8 RCV_Complete; //接收完成标志 1为完成
extern u8 SEND_Complete; //发送完成标志 1为完成
//模式控制
#define RS485_TX_EN PDout(7) //485模式控制.0,接收;1,发送.
#endif
//C文件
#include "stm32f10x.h"
#include "led.h"
#include "sys.h"
#include "delay.h"
#include "Modbus.h"
u8 RCV_Complete_Temp; //一帧接收完成缓存(1为完成)
u8 SEND_Complete_Temp; //一帧发送完成缓存(1为完成)
u8 RCV_Complete; //一帧接收完成(1为完成)
u8 SEND_Complete; //一帧发送完成(1为完成)
s8 RCV_Num_Temp; //用来表示接受到的一帧有效的字节数临时缓存(从功能码到CRC校验
u8 RCV_Num; //用来表示接受到的一帧有效的字节数(从功能码到CRC校验)
u8 SEND_Num; //用来表示待发送的一帧有效字节数
u8 RCV_Buffer_Temp[210]; //用来存放接收到的一帧完整的数据临时缓存(第一个字节用来存放接收到的有效字节数,也就是数组中
u8 RCV_Buffer[210]; //用来存放接收到的一帧完整的数据(第一个字节用来存放接收到的有效字节数,也就是数组中的有效字节数)
u8 SEND_Buffer[210]; //用来存放待发送的完整的一帧数据(第一个字节用来存放待发送的有效字节数,也就是数组中的有效字节数)
void RS485_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART2_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); //使能GPIOD时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE); //使能GPIOF时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //使能USART2时钟
USART_DeInit(USART2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //PD7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2; //PA2
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3; //PA3
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; //下拉输入
GPIO_Init(GPIOF,&GPIO_InitStructure);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,ENABLE);//复位串口2
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2,DISABLE);//停止复位
USART2_InitStructure.USART_BaudRate=115200; //波特率115200
USART2_InitStructure.USART_WordLength=USART_WordLength_8b; //数据位8位
USART2_InitStructure.USART_StopBits=USART_StopBits_1; //停止位1位
USART2_InitStructure.USART_Parity=USART_Parity_No ; //无校验
USART2_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //无硬件流
USART2_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; //发送/接收使能
USART_Init(USART2,&USART2_InitStructure); //初始化串口成员变量
USART_Cmd(USART2,ENABLE); //串口使能
NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn; //USART2全局中断
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; //通道使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; //子优先级为1
NVIC_Init(&NVIC_InitStructure); //初始化中断成员变量
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); //开RXNE中断使能
USART_ITConfig(USART2,USART_IT_IDLE,ENABLE); //开IDLE中断使能
RS485_TX_EN=0; //默认为接收使能
}
//接收发送模式设置函数
FlagStatus RCV_SEND_Mod(u8 rcv_complete, u8 send_complete)
{
FlagStatus a;
if((rcv_complete==0)||((RCV_Complete_Temp==0)&(send_complete==1))) //如果接收未完成或发送完成,则接收
{
USART_ClearFlag(USART2,USART_FLAG_TC); //清除发送完成标志位
rcv_complete=0; //清除接收完成标志
RS485_TX_EN=0; //设置为接收模式
a=SET;
}
else if((SEND_Complete_Temp==0)&(rcv_complete==1)) //如果接收完成则发送
{
send_complete=0; //清除发送完成标志
RS485_TX_EN=1; //设置为发送模式
a= RESET;
}
return a;
}
//接收中断函数
void USART2_IRQHandler(void) //数据接收中断
{
u8 Clear=Clear;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //如果接收到了1个字节
{
if(RCV_Num_Temp<64)
{
RCV_Buffer_Temp[RCV_Num_Temp++]=USART2->DR; //读取收到的数据,清除RXNE中断
LED0=0; //接收指示
}
}
if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //如果接收到了1帧数据
{
LED0=1;
Clear=USART2->SR; //读SR寄存器
Clear=USART2->DR; //读DR寄存器(先读SR再读DR,就是为了清除IDLE中断
RCV_Complete_Temp=1; //一帧接收完成临时缓存(1为完成)
}
}
//数据帧接收函数
void RS485_Receive_Data(void)
{
u8 i;
if(RCV_Complete_Temp==1) //如果接收完1帧数据,则开始另存
{
RCV_Num=RCV_Num_Temp;
for(i=0;i<RCV_Num;i++)
{
RCV_Buffer[i]=RCV_Buffer_Temp[i];
RCV_Buffer_Temp[i]=0X00;
}
RCV_Num_Temp=0; //数据帧字节长度临时缓存设初值
SEND_Complete_Temp=0;
RCV_Complete=1; //置位接收完成标志
delay_ms(1);
}
}
//数据帧发送函数
void RS485_Send_Data(void)
{
u8 t;
for(t=0;t<RCV_Num;t++) //循环发送数据
{
LED1=0; //发送指示
USART_SendData(USART2,RCV_Buffer[t]);
RCV_Buffer[t]=0X00;
delay_ms(2);
}
if(USART_GetFlagStatus(USART2, USART_FLAG_TC)==SET) //判断是否发送完成
{
LED1=1;
RCV_Num=0;
RCV_Complete_Temp=0;
SEND_Complete_Temp=1;
SEND_Complete=1; //置位发送完成标志
delay_ms(1);
}
}
//main()
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "Modbus.h"
int main(void)
{
while(1)
{
if(RCV_SEND_Mod(RCV_Complete, SEND_Complete)==SET)
{
RS485_Receive_Data();
}
if(RCV_SEND_Mod(RCV_Complete, SEND_Complete)==RESET)
{
RS485_Send_Data();
}
}
}
|
-
|