OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4925|回复: 3

还是GPIO口采集数据的问题,请大家帮忙看看,谢谢啦。

[复制链接]

8

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
75
金钱
75
注册时间
2014-5-16
在线时间
8 小时
发表于 2014-7-16 18:10:10 | 显示全部楼层 |阅读模式
5金钱
以前就问过这个问题,原子哥给我了修改的建议,改了以后情况有所改善,但误码率依然很高。
请大家再帮我看看,是不是还有什么地方我没有考虑到的?

用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]


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

8

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
75
金钱
75
注册时间
2014-5-16
在线时间
8 小时
 楼主| 发表于 2014-7-16 18:26:34 | 显示全部楼层
典型的错误数据是这样的:


红框里多了两个“0” 导致后面接收到的数据都没有对齐。。。



只应该接收到1或0,显然不能接收到E1这样的数据。。

我怀疑是通过串口发送数据的过程中出的错。是不是发送数据的过程中被中断了?请大家帮我看看应该怎么改,谢谢了。

回复

使用道具 举报

20

主题

562

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
670
金钱
670
注册时间
2012-2-28
在线时间
0 小时
发表于 2014-7-16 18:57:26 | 显示全部楼层
建议楼主先将串口的功能关闭掉,STM32不向上位机发送数据,而STM32将接收到同步RS232数据先暂存在缓冲中,过一段时间之后,看看接收到的数据是否正确

如果正确的话,那应该就是中断干扰了串口的发送,可以改用DMA发送方式

如果接收到的数据出了错误,可能是接受同步数据时出错,调试调试硬件,改改代码,直到不出错为止
努力,前进。
回复

使用道具 举报

8

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
75
金钱
75
注册时间
2014-5-16
在线时间
8 小时
 楼主| 发表于 2014-7-17 20:39:14 | 显示全部楼层
谢谢2楼!

在用GPIO口采集数据的时候一般采用那些方式?有没有套路可循?我刚刚接触嵌入式开发,怕有问题没有考虑到,还请大家多指点,谢谢。
还有就是,在中断处理和发送数据的过程中,需不需要把中断关闭?或者还有其他的什么需要处理的?如果关闭中断我担心会错过数据采集。这种情况一般是要怎么处理?

另外,DMA的方式发送数据是不是就能避免中断干扰数据发送了?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-5 01:43

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表