精华内容
下载资源
问答
  • linux中串口传输剔除错误数据的方法

    千次阅读 2014-07-11 09:12:47
    串口传输中有些朋友可能会经常遇到

            串口传输中有些朋友可能会经常遇到数据丢失的情况,像我遇到情况是:数据没传输个几十次,收到的数据就会有一个有问题。 出现这种现象的原因主要是波特率的原因,我这里主要是因为我的485转串口电路中用的光耦是til117,这种光耦的波特率是多少我到网上查了下,可惜资料里面好像都 没说它的波特率,初步估计这是一个低速光耦,因为如果把串口速度调到9600的话,收到的数据完全有问题。不过写的数据没问题,但返回数据接收后不对。把波特率改成2400后数据基本正常了,但是每个一段时间就会有一个错误。应该还是光耦问题,我本来想把它速度再改慢点,但是改成1200之后板子不知道什么情况,运行程序就卡死。。没办法改成1200了,那怎么办?我就想着把错误数据剔除掉。

           方法其实不难。我们向从设备发送一个指令,从设备解析之后返回一个数据。这个返回过程中数据的传输很短。而linux中刚好有一个timer定时器,我们可以这样处理。初始化一个定时器,时间定为几百毫秒。在返回数据的中断处理函数中禁止定时器,等处理完之后又使能定时器。在定时器的处理函数中将数组的下标变成0。这是什么意思呢?我这种方法处理的是这样一种情况, 比如说我要接收7个数据,但是某次出错只能发送3个数据。(这样下次我接收7个正确的数据的时候,它在数组中不是一次按照0-7接收的,而是4-7,然后再0-2,数组完全打乱,这样如果你有CRC校验,那肯定是一直是错误。)应用程序每隔几分钟或者更长时间发送一次指令,所以从设备每隔同样长的时间才发送一个数据。而传输过程中时间很短,如果发了7个数据,那么定时器在这7个数据发送时不起作用,如果它只发了比如3个,那么在从第3到第4这段时间里它就不会再进入接收中断处理函数。这个时候,前面我们在接收中断里面把定时器禁止后又让他使能了,那么几百毫秒之后第4个数据没来,那么定时器就起作用了,这个时候就把接收数组的下标重新变为0,这样就能避免出现错误后,下次接收到正确的数据的时候,它不再是按照正常的0-7的下标排列的情况。当然你还可以给自己接收的数据再加上校验。CRC校验不正确的话就不传输

    展开全文
  •  如果使用的是内部的16MHz时钟,这三行初始化代码应该可以启动串口传输数据,但是我发现数据在传输的过程中出错,刚开始也怀疑是串口配置出错,假如配置出错,理论上是不会收到数据的,上面的代码能在内部时钟下...

            最近有个小东西用到STM8S来驱动,之前用STM8S使用的是内部自带的16MHz RC时钟,尚未尝试过使用外部晶振作为主时钟。今天记录一下使用外部晶振时遇到的一个问题。

          老规矩,在进行程序设计时,首先初始化时钟,本次使用的是STM8S103F3P6芯片,8MHz的外部晶振,为了方便内外部时钟切换,结合资料写了两个切换函数

    /***********************************************
    *描述:采用内部16MHz的RC时钟为主时钟
    *      初始化时钟为1分频 16M,无外部晶振
    *版本:V1.0
    *作者:
    ************************************************/
    void HsiInit(void)
    {
        CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
    }
    /***********************************************
    *描述:采用8M外部晶振为主时钟,用于时钟切换    
    *版本:V1.0
    *作者:
    ************************************************/
    void HseInit(void)
    {   
      CLK_DeInit();                                         //时钟初始化
      CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);              //8MHz,不分频
      CLK_HSECmd(ENABLE);                                   //外部时钟开  
      CLK_HSICmd(ENABLE);                                   //内部RC开 
      while(SET != CLK_GetFlagStatus(CLK_FLAG_HSERDY));    //等待外部晶振起振 
      CLK_ClockSwitchConfig(CLK_SWITCHMODE_MANUAL,CLK_SOURCE_HSE,DISABLE,CLK_CURRENTCLOCKSTATE_DISABLE);
      CLK_ClockSwitchCmd(ENABLE);                           //开始切换 
    }

    在主函数调用所需的时钟函数即可,为了验证外部时钟是否切换成功,我在定时器1的通道1输出PWM进行验证,所幸得到了想要的波形,定时器1的配置如下

    /***********************************************
    *描述:TIM1CH1(PC6)输出PWM,频率为1K
    *      定时器时钟为外部的8MHz
    *版本:V1.0
    *作者:
    ************************************************/
    void TIM1_Init(void)
    {
        TIM1->EGR = 0x01;//重新初始化定时器1
        TIM1->CR1 = 0x00;//边沿对齐方式,向上计数,发生更新事件,计数器不停止更新
        TIM1->RCR = 0x00;//重复计数器的值为0,计时时间到,重复多少次产生中断,该值是重复多少次那个值
        
        //设定预分频为,80分频 8M
        TIM1->PSCRH =0x00;  //PWM的时钟 影响周期
        TIM1->PSCRL =0x4f;  //80分频,TIM1的时钟为100K
    
        TIM1->ARRH = 0x00;  //设定重装载值
        TIM1->ARRL = 0x63;  //计数100次,等于T,即1ms(f=1K),每10us计一个数
    
        //CH1
        TIM1->CCER1 = 0x01; //CC2ER1开启CH1,CC1配置入输出,低电平有效
        TIM1->CCMR1 = 0x68; //PWM模式1,使能预装载
    
        //设置占空比
        TIM1->CCR1H = 0x00;
        TIM1->CCR1L = 0x0A;  // 占空比值
    
        TIM1->OISR &= ~0x03;
        TIM1->BKR |= 0x80;   //刹车
        TIM1->CR1 |= 0x01;  //使能TIM1计数器
        
    //    GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_OUT_PP_LOW_FAST);
        GPIOC->DDR|=0xff;//输出
        GPIOC->CR1|=0xff;//推挽
        GPIOC->CR2|=0xf0;//速度
    }

    接下来开始进入本次主题,采用8MHz外部时钟时,串口1传输数据异常。开始时串口初始化函数如下,使用波特率是9600

    void Uart1_Init(u32 Baudrate)
    {
        UART1_DeInit(); 
        UART1_Init((u32)Baudrate, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
        UART1_Cmd(ENABLE );  //启用串口
    }

            如果使用的是内部的16MHz时钟,这三行初始化代码应该可以启动串口传输数据,但是我发现数据在传输的过程中出错,刚开始也怀疑是串口配置出错,假如配置出错,理论上是不会收到数据的,上面的代码能在内部时钟下正常传输数据,在外部时钟下传输出错,那很大可能就是波特率出现了问题。

          串口初始化的波特率是9600,串口调试助手在9600的波特率下得不到正确的数据,printf打印出来的是乱码

    啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧
    槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff
    啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧
    槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff
    啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧
    槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff

    当我把串口调试助手的波特率改为4800后,神奇的一幕出现了

    ART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!

    为什么呢?很好奇发生了什么,我把波特率两个寄存器值打印出来

    UART1->BRR2: 2
    UART1->BRR1: 68
    UART1->BRR2: 2
    UART1->BRR1: 68
    UART1->BRR2: 2
    UART1->BRR1: 68
    UART1->BRR2: 2
    UART1->BRR1: 68

          结合STM8S参考手册,将这两个寄存器的值还原,得到UART_DIV = 0x0682,十进制就是UART_DIV = 1666,按照公式:

                                         UART_DIV  = F / Baudrate,其中F是主时钟频率,Baudrate是波特率,为9600

    那么主时钟频率 = 1666 * 9600 = 15993600,接近16MHz,通过上面可以观察到,UART_DIV = 1666对应的是16MHz,那么8MHz应该为多少?

    UART_DIV  =  8000 000 / 9600 = 833.3,即UART_DIV  = 0x0341

    参考数据手册的设置规则,BRR1和BRR2的值应该为

        UART1->BRR2 = 0x01;
        UART1->BRR1 = 0x34;

    所以串口初始化函数应该为(注意必须是先设置BRR2,再设置BRR1)

    void Uart1_Init(u32 Baudrate)
    {
        UART1_DeInit(); 
        UART1_Init((u32)Baudrate, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
        UART1->BRR2 = 0x01;
        UART1->BRR1 = 0x34;
        UART1_Cmd(ENABLE );  //启用串口
    }

    此时,再将串口调试助手的波特率设置为9600,可以得到如下数据

    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34

    至此,串口调试完成,引起传输数据出错,应该是库函数计算波特率是以内部的16MHz频率作为标准,假如你要用到其他频率,需要重新设置BRR1和BRR2这两个寄存器的值。

    展开全文
  • STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成,否则,发送不成功,使用stm32f10x调试串口通讯时,发现一个出错的现象,硬件复位重启之后,发送测试数据0x01 0x02 0x03...

    STM32串口发送必须先检测状态,否则第一个字节无法发出,发送完毕,必须检测发送状态是否完成,否则,发送不成功,使用stm32f10x调试串口通讯时,发现一个出错的现象,硬件复位重启之后,发送测试数据0x01 0x02 0x03 0x04..接收端收到的数据为:0x02 0x03 0x04,第一个数据丢失。换成发送别的数值的数据,如0x06 0x0ff,则接收到0x0ff,0x06丢失。错误依旧。

    故障排除过程:

    1、刚开始怀疑是接收端的错误,我是使用电脑串口,运行串口辅助调试工具接收,换成其他软件后,发现故障依旧,而且电脑软件一直是开启状态,不像和电脑软件有关。

    2、使用单步调试,单步运行各个发送指令,都正常。能收到0x01 0x02 0x03 0x04的数据。间接的排除了不是电脑软件的问题,而是其他的错误。

    3、单步调试运行虽然正常了,但连续运行时,错误依旧。现在有点摸不到头绪了,单步运行正常,看起来编程没有出错,那故障在哪里呢?测试程序如下

    USART_SendData(USART2, 0x01); //A

    while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //B

    USART_SendData(USART2, 0x02); //C

    while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);

    USART_SendData(USART2, 0x03);

    while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);

    USART_SendData(USART2, 0x04);

    while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);

    4、猜测,也许是因为某个特殊原因,使第二个数据覆盖了首个数据,使得首个数据丢失。假设:在执行B指令时,USART的 TC 状态位==SET,那么就会紧接着执行C指令,也就有可能发生数据的覆盖。于是,在A指令前,加入如下指令:USART_ClearFlag(USART2,USART_FLAG_TC);

    5、加入上一条指令后,运行,错误消失了。说明上一个假设,应该是成立的。

    6、查阅stm32f10x参考手册,找到这样一句话:

    TC:发送完成

    当包含有数据的一帧发送完成后,由硬件将该位置位。如果USART_CR1中的TCIE为1,则产生中断。由软件序列清除该位(先读USART_SR,然后写入USART_DR)。TC位 也可以通过写入0来清除,只有在多缓存通讯中才推荐这种清除程序。

    0:发送还未完成;1:发送完成。

    7、注意到这一句:由软件序列清除该位(先读USART_SR,然后写入USART_DR)。 也就是说,要先read USART_SR,然后write USART_DR,才能完成TC状态位的清除。而硬件复位后,串口发送的首个数据之前没有read SR的操作,是直接write DR,也就是说,TC没有被清除掉。 说明第4步的猜测是对的。

    8、那么,应该把指令A前面加的USART_ClearFlag(USART2,USART_FLAG_TC); 改为USART_GetFlagStatus(USART2, USART_FLAG_TC);,应该也能消除错误。测试后证实,确实如此,在发送首个数据之前,先读取一下USART_SR,那么就不会出现首个数据丢失的情况了。

    9、总结:硬件复位后,串口发送首个数据之前,先读取一下USART_SR,则能够保证首个数据发送时,不出现覆盖的情况。当然,也有别的方法,比如先清除TC状态位,或是,在write USART_DR之后,加入一个小延时,让数据发送完毕,应该也能间接排除这个错误。

    展开全文
  • 今天做实验的时候,要用到两块32的板子进行通讯,在这里将其命名为A板和B板,使用的是32引脚直接引出的TTL串口,由于忘记带导线了,所以在做实验的时候找了两根长短不一的线,长线大概一米用在A板和B板的地线的连接...

           今天做实验的时候,要用到两块32的板子进行通讯,在这里将其命名为A板和B板,使用的是32引脚直接引出的TTL串口,由于忘记带导线了,所以在做实验的时候找了两根长短不一的线,长线大概一米用在A板和B板的地线的连接,然后短线大概半米用在B板子的接收端(RXD),相对应用在A板子的发送端(TXD),由于通讯的时候值只涉及A板向B板发送数据,所以B板的发送端和A板的接收端就没有再连接起来了,本来就是缺少导线的【笑哭】【笑哭】【笑哭】,关于电源线3.3V为什么不接,因为两块板子间的串口没有使用光耦进行隔离,就不需要接上电源线,反而接上电源线后,由于两块板子的电源可能会有点差别,有可能导致数据传输错误,如果使用了光耦进行隔离,那么必须接上电源线,通讯才可正常进行,

           那么在做实验的时候,和调试的时候同样的通讯协议,代码也是一样的,在A板向B板发送数据后,B板接收的数据总是错的,有点糊涂了,明明在调试的时候是收发正常的,数据并没有出现错误,然后检查波特率是否设置一样,A板和B板的波特率都是设置为9600bps,没有错误,用A板发送了好几次,B板接收到的数据都是错误的,想着是不是就是线的长度不同导致的,然后就再去找了根大约一米的线,给前面A板和B板的数据收发端进行连接,然后再进行通讯,通讯正常,A板发送的数据和B板接收的数据是吻合的。

           第一次遇到这种问题,所以记一下,以后用串口传输的时候要注意下。数据线和电源线的长度要差不多才行

    展开全文
  • 最近调试串口时发现,每次从停止模式唤醒后发送的第一条数据老是出错,出错现象是所发送的数据前面会出现多出一些乱码...当前传输数据将会丢失。 ”,我遇到的这种出错问题可能就是这个,进入低功耗之前还处在发送状
  • 系统结构如图所示,要求,PC端用串口精灵/串口调试助手等软件实现,通信波特率19.2kbps,通过PC端每次发送数据,控制8bitLED完成下表功能: 命令 LED状态 SX 单个LED顺序流水(0-7) NX 单个LED逆序流水(7-0) JF ...
  • 原因分析总结: 1、初始化了吗? 有一次,串口始终返回的数据只有一个字母,所以我们一直怀疑是数据被覆盖或者... 倾角传感器传输端口已经由一般串口改为485接口,232的收发是由两条线路来分别司职收和发,485的...
  • LINUX串口文件传输

    2018-07-25 08:55:12
    串口文件传输数据帧格式:0xAA+0xAA+序号+数据长度+50字节数据+校验和。支持错误重传。 用法: 发: ./test /devttyUSB0 0 a.txt 收: ./test /devttyUSB1 1 b.txt a.txt为要发送的文件,b.txt为保存的文件 test...
  • 嵌入式系统中,关于... 关于串口传输,个人觉得采用modbus协议来接受数据是比较合理的,采用3.5char字符的超时机制,接受的时候如果判断超时,就当作一帧数据进行处理,所以这种情况,帧格式没有那么讲解,发送...
  • 尽管比按字节(byte)传输的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据串口通信中比较重要的参数包括波特率、数据位、停止位及校验位,通讯双方需要约定一致的数据格式才能正常收发...
  • 问题是这样的,我用python代码向ARDUINO中传输数据的时候,只会在最初的第一次运行时向串口传输正确的字符串“openthelight”,当while循环运行结束的时候就会出现数据刷新的情况,从代码上没看出什么毛病,求大神...
  • 但是一用单片机和工控机直接通信就出现通信故障,经过排查发现单片机老是接收到错误数据0X80; 当时的波特率是115200,后来查找资料说这是MAX3232ESE-T芯片的极限通信速率了,果断把波特率降低为19200或者其他低于...
  • 原因分析总结: 1、初始化了吗? 有一次,串口始终返回的数据只有一个字母,所以我们一直怀疑是...倾角传感器传输端口已经由一般串口改为485接口,232的收发是由两条线路来分别司职收和发,485的通却是两条线路通...
  • 使用pyserial进行串口传输一、安装pyserial以及基本用法在cmd下输入命令pip install pyserial注:升级pip后会出现 "‘E:\Anaconda3\Scripts\pip-script.py' is not present."错误使用 easy_install pip命令就能解决...
  • { printf("往串口发送数据成功!\n" ); break; } } //CloseHandle(hcom); }; DWORD WINAPI Write(LPVOID lpParamter) { //读取串口设置 LPTSTR lpPath = new char[MAX_PATH]; int COM4BaudRate; ...
  • 使用pyserial进行串口传输一、安装pyserial以及基本用法在cmd下输入命令pip install pyserial注:升级pip后会出现 "‘E:Anaconda3Scriptspip-script.py" is not present."错误使用 easy_install pip命令就能解决,换...
  • 打开串口后,就开始了自动接收数据,接收完成后,按下“停 止接收数据”;如果要发送数据,请点击“发送键”,发送完成,会弹出“发送完成”。 软件测试情况:发送功能用“超级终端多次测试”,10M内,没发生错误。...
  • 使用pyserial进行串口传输 一、安装pyserial以及基本用法 在cmd下输入命令pip install pyserial 注:升级pip后会出现 “‘E:\Anaconda3\Scripts\pip-script.py’ is not present.”错误 使用 easy_install pip命令就...
  • 一、安装pyserial以及基本用法使用pyserial进行串口传输,在cmd下输入命令pip install pyserial注:升级pip后会出现 "‘E:\Anaconda3\Scripts\pip-script.py' is not present."错误使用 easy_ins...
  • 一、安装pyserial以及基本用法使用pyserial进行串口传输,在cmd下输入命令pip install pyserial注:升级pip后会出现 "‘E:Anaconda3Scriptspip-script.py' is not present."错误使用 easy_install pip...
  • 一、安装pyserial以及基本用法使用pyserial进行串口传输,在cmd下输入命令pip install pyserial注:升级pip后会出现 "‘E:\Anaconda3\Scripts\pip-script.py' is not present."错误使用 easy_ins...
  • 用Python串口实时显示数据并绘图

    万次阅读 多人点赞 2019-05-06 21:27:45
    使用pyserial进行串口传输 一、安装pyserial以及基本用法 在cmd下输入命令pip install pyserial 注:升级pip后会出现 "‘E:\Anaconda3\Scripts\pip-script.py’ is not present."错误 使用 easy_install pip命令...
  • 使用pyserial进行串口传输 一、安装pyserial以及基本用法 在cmd下输入命令pip install pyserial 注:升级pip后会出现 "‘E:\Anaconda3\Scripts\pip-script.py’ is not present."错误 使用 easy_install pip命令...
  • 用Python串口实时显示数据并绘图使用pyserial进行串口传输一、安装pyserial以及基本用法在cmd下输入命令pip install pyserial注:升级pip后会出现"‘E:\Anaconda3\Scripts\pip-script.py’ is not present."错误使用...
  • 1.通过STM32cubemx配置时钟,串口参数 2.配置串口DMA,normal模式,...4.定义局部数组,HAL_UART_Transmit_DMA发送,发现后面几个字节数据错误,把局部数组改为全局数组就没问题。 5.HAL_UART_Transmit发送局部或...
  • 今天尝试了使用Openmv用串口发送数据,32接收,遇到了一些坑,但是最后还是实现了,难住我的地方并不是关于传输的代码,而是那个板子串口3不知道因为什么原因接收到的数据错误的,这个原因正在寻找,找到了再记录...
  • 使用modbus协议实现串口数据通信 Modicon控制器使用的公共语言是modbus协议[1,7]。这是一个开放的协议,它定义了信息结构,使得控制器能认出和利用这些信息,不管它们在什么类型的网络上传输。它描述了该控制器发送...
  • 关于linux下串口通信传输换行符

    千次阅读 2018-03-21 10:13:15
    新手初次编写,如有错误请多指正。在做硬件远程控制时,一般都会需要在包的末尾加一个回车符来判断命令发送完成。而用scanf输入到buff的时候会遇到按下回车,输入就结束了。曾试过多种方法,始终无法在发送的数据里...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 270
精华内容 108
关键字:

串口传输数据错误