以前就问过这个问题,原子哥给我了修改的建议,改了以后情况有所改善,但误码率依然很高。
请大家再帮我看看,是不是还有什么地方我没有考虑到的?
用MiniSTM32从一个设备上采集数据,设备使用同步RS232口输出数据,并将数据封装成HDLC帧。我的想法是使用MiniSTM32将同步RS232数据转换成异步RS232的数据,这样就可以发到PC机的串口上由PC机采集数据。
设备输出的时钟为9.6k,下降沿触发,每次发送1位数据。时钟接在MiniSTM32的PC12口上,数据接在PC11口上。在PC12口上设置中断,每遇到一个下降沿就从PC11口上读取1位数据,随后把这个数据(0或者1)从usart1上发送给PC机。
以前是采集到数据后组装成帧再发给PC机,后来为了尽量减少中断里面执行的代码,我把装帧的代码也移到PC上了,相当于每采集到1位数据就发给PC机,可是这么做了居然都有很高的误码率。
使用下面的代码进行采集:
[mw_shl_code=c,true]#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "exti.h"
#include "led.h"
#include "key.h"
#include "stm32f10x.h"
#include "string.h"
//char usart_send_buff[256];
//u16 usart_send_len;
//输入数据
u8 RecvData;
//输入的比特位计数;
u8 BitCount;
//帧起始标志
u8 FrameBegin;
//1计数
u8 OneCount;
//同步字
u8 SyncWord;
//帧缓存
u8 FrameBuff[256];
//帧长度
u8 FrameLength;
//包起始标志
u8 PacketHead;
//包结束标志
u8 PacketTail;
//PC11脚上读到的数据
u8 ReadValue;
//PC11脚上真实读到的数据
u8 RealRV;
//PC11脚上真实读到的数据(1计数)
u8 RealRV1Count;
//出现错误的时候
u8 Err;
//同步标志
u8 IsSync;
//发送数据
u8 SendData;
//FIFO
u8 FIFOBuff[4096];
//FIFO 输入数据指针
u16 in_ptr;
//FIFO 输出数据指针
u16 out_ptr;
//fputc函数使用的临时指针
FILE *p;
//每个下降只发送1个字节数据
u8 IsFallEdge;
int main(void)
{
//初始化与LED连接的硬件接口
LED_Init();
//外部中断初始化
EXTIX_Init();
//初始化延迟
delay_init();
//初始化串口
usart1_init(115200);
//初始化输入口
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);//使能PORTA,PORTC时钟
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试
//初始化PORTC.11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PC11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PC11设置成输入,默认上拉
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //PC11设置成输入,先试试浮空
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.11
//初始化PORTC.12
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PC12
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.12
//初始化数据处理函数
RecvData = 0;
BitCount = 0;
FrameBegin = 0;
OneCount = 0;
SyncWord = 0;
memset(FrameBuff,0,256);
FrameLength = 0;
PacketHead = 0x55;
PacketTail = 0xAA;
ReadValue = 0;
Err=0;
IsSync = 0;
SendData = 0;
memset(FIFOBuff,0,4096);
in_ptr = 0;
out_ptr = 0;
IsFallEdge = 0;
while(1)
{
if(IsFallEdge == 0)
{
continue;
}
GPIO_SetBits(GPIOD,GPIO_Pin_2);
if(in_ptr != out_ptr)
{
if(out_ptr == 4096)
{
out_ptr = 0;
}
fputc(FIFOBuff[out_ptr],p);//数据发送
//delay_us(20);
out_ptr++;
IsFallEdge = 0;
}
}
}
[/mw_shl_code]
中断是这样的
[mw_shl_code=c,true]#include "exti.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "usart.h"
#include "string.h"
//////////////////////////////////////////////////////////////////////////////////
//extern char usart_send_buff[256];
//extern u16 usart_send_len;
//输入数据
extern u8 RecvData;
//输入的比特位计数;
extern u8 BitCount;
//帧起始标志
extern u8 FrameBegin;
//1计数
extern u8 OneCount;
//同步字
extern u8 SyncWord;
//帧缓存
extern u8 FrameBuff[256];
//帧长度
extern u8 FrameLength;
//包起始标志
extern u8 PacketHead;
//包结束标志
extern u8 PacketTail;
//PC11脚上读到的数据
extern u8 ReadValue;
//PC11脚上真实读到的数据
extern u8 RealRV;
//PC11脚上真实读到的数据(1计数)
extern u8 RealRV1Count;
//出现错误的时候
extern u8 Err;
//同步标志
extern u8 IsSync;
//发送数据
extern u8 SendData;
//FIFO
extern u8 FIFOBuff[4096];
//FIFO 输入数据指针
extern u16 in_ptr;
//FIFO 输出数据指针
extern u16 out_ptr;
//fputc函数使用的临时指针
extern FILE *p;
//每个下降只发送1个字节数据
extern u8 IsFallEdge;
//外部中断初始化函数
void EXTIX_Init(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//外部中断,需要使能AFIO时钟
//GPIOC.12 中断线以及中断初始化配置
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource12);
EXTI_InitStructure.EXTI_Line=EXTI_Line12;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; //使能按键所在的外部中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2,
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道
NVIC_Init(&NVIC_InitStructure);
}
void EXTI15_10_IRQHandler(void)
{
RealRV1Count = 0;
if(EXTI_GetITStatus(EXTI_Line12)!=RESET)
{
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
//延时10微秒等待信号稳定
delay_us(2);
//读取针脚上的数据 -- 2
ReadValue = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_11);
if(ReadValue==0x01)
{
RealRV1Count++;
}
delay_us(2);
//读取针脚上的数据 -- 4
ReadValue = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_11);
if(ReadValue==0x01)
{
RealRV1Count++;
}
delay_us(2);
//读取针脚上的数据 -- 6
ReadValue = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_11);
if(ReadValue==0x01)
{
RealRV1Count++;
}
//delay_us(2);
//读取针脚上的数据 -- 8
ReadValue = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_11);
if(ReadValue==0x01)
{
RealRV1Count++;
}
//delay_us(2);
//读取针脚上的数据 -- 10
ReadValue = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_11);
if(ReadValue==0x01)
{
RealRV1Count++;
}
if(RealRV1Count>=3)
RealRV = 1;
else
RealRV = 0;
if(in_ptr == 4096)
{
in_ptr = 0;
}
FIFOBuff[in_ptr] = RealRV;
in_ptr++;
IsFallEdge = 1;
EXTI_ClearITPendingBit(EXTI_Line12);
}
}
[/mw_shl_code]
串口设置
[mw_shl_code=c,true]//初始化IO 串口1
//bound:波特率
void usart1_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟
USART_DeInit(USART1); //复位串口1
//USART1_TX PA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9
//USART 初始化设置
USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
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_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
USART_Cmd(USART1, ENABLE); //使能串口
}[/mw_shl_code]