中级会员
 
- 积分
- 309
- 金钱
- 309
- 注册时间
- 2016-5-20
- 在线时间
- 45 小时
|
10金钱
/*********************************************************************************************************
说明:1.这个程序我是拿来做485串口通讯用的,才刚刚起步就遇到了这样的问题,请高人指点,谢谢!
2.这个程序编译都没有问题,可以直接下载到开发板,我用的是精英板
3.程序下载到开发板后,用串口助手发数据给它,然后再返回收到的数据,串口助手发一次,它就返回一次
4.我现在遇到的问题是:串口助手第一次发数据给它,能返回数据,并且都正确;但是再次发数据给它,就不能返回数据了
5.据我所看到的情况就是,再次发数据给它时,它就不收数据
6.下面附上串口助手的图片,这款串口助手软件用起来很不错,推荐给大家
7.由于自己刚刚接触STM32,不是很熟悉,再加上C语言也不是很好,所以有劳大家了,在此一并感谢
*********************************************************************************************************/
//头文件
#ifndef __MODBUS_H
#define __MODBUS_H
#include "sys.h"
void RS485_Init(void);
void ID_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 Mod_Id=0; //用来标志作为从站的站号
u8 RCV_Complete; //一帧接收完成(1为完成)
u8 SEND_Complete; //一帧发送完成(1为完成)
u8 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); //开串口接收中断使能
RS485_TX_EN=0; //默认为接收使能
}
//通过GPIOF_PIN0-GPIOF_PIN3来设置1-16个站号
void ID_Init(void)
{
GPIOF ->IDR &=0X0000;
Mod_Id = GPIOF ->IDR&0x0000FFFF;
//Mod_Id = GPIO_ReadInputData(GPIOF);
Mod_Id += 1;
}
//接收发送模式设置函数
FlagStatus RCV_SEND_Mod(u8 rcv_complete, u8 send_complete)
{
if((rcv_complete==0)||(send_complete==1)) //如果接收未完成或发送完成,则接收
{
USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除串口接收中断标志位
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE); //开串口接收中断使能
USART_ClearFlag(USART2,USART_FLAG_TC); //清除发送完成标志位
if(send_complete==1) rcv_complete=0;
return SET;
}
if(rcv_complete==1) //如果接收完成则发送
{
send_complete=0;
return RESET;
}
return RESET;
}
//接收中断函数
void USART2_IRQHandler(void) //数据接收中断
{
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收到数据
{
if(RCV_Num_Temp<64)
{
RCV_Buffer_Temp[RCV_Num_Temp]=USART_ReceiveData(USART2); //读取接收到的数据
RCV_Num_Temp++; //接收数据增加1
}
}
}
//数据帧接收函数
void RS485_Receive_Data(void)
{
u8 i;
RCV_Num=0;
if(USART_GetFlagStatus(USART2,USART_FLAG_IDLE) == SET) //如果总线空闲,则开始接收
{
RCV_Num=RCV_Num_Temp;
if(RCV_Num) LED0=0; //接收指示
delay_ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
if(RCV_Num==RCV_Num_Temp&&RCV_Num)//接收到了数据,且接收完成了
{
for(i=0;i<RCV_Num;i++)
{
RCV_Buffer[i]=RCV_Buffer_Temp[i];
}
LED0=1; delay_ms(100);
RCV_Num_Temp=0; //清除数据帧字节长度缓存
USART_ITConfig(USART2,USART_IT_RXNE,DISABLE); //关串口接收中断使能
RS485_TX_EN=1; //设置为发送模式
RCV_Complete=1; //置位接收完成标志
}
}
}
//数据帧发送函数
void RS485_Send_Data(void)
{
u8 t;
LED1=0; //发送指示
for(t=0;t<RCV_Num;t++) //循环发送数据
{
USART_SendData(USART2,RCV_Buffer[t]);
delay_ms(2);
}
// while(USART_GetFlagStatus(USART2, USART_FLAG_TC) ==RESET);
if(USART_GetFlagStatus(USART2, USART_FLAG_TC)==SET) //判断是否发送完成
{
LED1=1;
RCV_Num=0;
RS485_TX_EN=0; //设置为接收模式
SEND_Complete=1; //置位发送完成标志
}
}
//主函数
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "beep.h"
#include "delay.h"
#include "Modbus.h"
int main(void)
{
u8 key;
u8 RS485_TX_RX_ON=1; //发送接收使能
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init(); //按键初始化
delay_init(); //延时函数初始化
RS485_Init(); //初始化RS485
ID_Init();
//BEEP_Init();
while(1)
{
key=KEY_Scan(0);
if(key==KEY0_PRES) //KEY0按下,发送一次数据
{
delay_ms(100);
if(key==KEY0_PRES)
{
RS485_TX_RX_ON=1;
}
}
if(RS485_TX_RX_ON==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();
}
}
}
}
|
-
最佳答案
查看完整内容[请看2#楼]
/***************************************************************************************************************
产生问题的原因是:接收发送模式设置函数的逻辑不对,下面附上改正后的这段程序;
另外多声明了两个全局变量 RCV_Complete_Temp SEND_Complete_Temp 用于对这段逻辑的辅助判断,这两个变量都分别在RCV_Complete SEND_Complete 的位置进行赋值;
******************************************************* ...
|