• 单片机模块化程序: 难道有环形队列串口发送数据就万事大吉了吗


    1.问个问题,下面程序有没有BUG

     

     2.环形队列虽然解决了一开始的中断发送数据覆盖问题,但是呢却引入了新的问题

    3.然后看看中断发送

    4.想没想明白是什么问题

     5.发送数据1 和发送数据2 之间没有延时......

    咱做程序的时候经常碰到各个地方都需要发送串口的数据,但是如果两个发送函数一个先发送完,另一个紧接着就发送了.......

    这时候就有问题了,发给一个设备,本来都是正确的数据,但是由于这么一整,数据便成了错的了.

    好现在解决这个问题

    主要目的就是发送的数据还需要管理一下,让发送的数据之间有时间间隔

    好,再加个环形队列

    这个环形队列呢,记录要发送的数据个数

    现在就有两个环形队列,

    一个环形队列数存储数据,就是咱一开始用的

    另一个环形队列是存储这次要发送的数据个数

    那么每次发送数据变为

    然后中断发送里面

    Usart1ManageSendDatLen记录的是这次发送的数据个数

    发送的时候Usart1ManageSendDatLen -- , 变为0,就说明发完了现在的数据了

    发送的数据个数是在定时器里面获取

        if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
      {        
        if(Usart1ManageSendDatLen>0 && rbCanRead(&Uart1rb)>0)//发送的数据个数大于0 ,环形队列可以读出来数据
        {
          rbRead(&Uart1rb, &Usart1SendDat, 1);//读取一个数据
          USART_SendData(USART1, Usart1SendDat);//发送
                Usart1ManageSendDatLen -- ;//发送的数据个数减一
        }
        else
        {
          //发送字节结束
          USART_ClearITPendingBit(USART1,USART_IT_TXE);
          USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
          USART_ITConfig(USART1, USART_IT_TC, ENABLE);
                Usart1ManageSendDatLen = 0;//发送完成,清零
        }
      }
      //发送完成
      if (USART_GetITStatus(USART1, USART_IT_TC) != RESET)
      {
        USART_ClearITPendingBit(USART1,USART_IT_TC);
        USART_ITConfig(USART1, USART_IT_TC, DISABLE);
      }

    定时器里面

    Usart1ManageSendDatLen = 0;说明发送完数据了

    然后 利用变量累加进行延时

    延时10Ms(自行调节,该变量控制两条数据发送的时间间隔)

    读取下保存每次发送多少数据的那个环形队列

    取出来这次要发送的数据个数然后赋值给 Usart1ManageSendDatLen 

    然后打开发送中断

    发送中断发送完数据又会出现 Usart1ManageSendDatLen = 0;

    然后一直这样工作

    这样的话,多条同时填充的数据,发送每一条数据的时间间隔是10Ms

    不会再出现整个发出去的情况了!

        if(Usart1ManageSendDatLen == 0)//没有在发送数据
        {
            Usart1ManageSendDelayCnt++;
            if(Usart1ManageSendDelayCnt>=10)//延迟10Ms
            {
                Usart1ManageSendDelayCnt = 0;
                if(rbCanRead(&Uart1rbManage)>0)//是不是有需要发送的数据
                {
                    //取出这次要发送的数据个数
                    rbRead(&Uart1rbManage, &Usart1ManageSendDatLen, 1);
                    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);//打开发送中断
                }
                else
                {
                    //没有数据发送的时候1Ms判断一次,延迟1Ms
                  Usart1ManageSendDelayCnt=10;
                }
            }
        }

    测试

    如果想测试的明显

    现在说下现在这个程序带来的新问题

    1.发送数据最低延迟 1Ms

      其实这个延迟再加点变量就可以解决,但是呢,我怕加多了,大家理解起来困难....

      所以先这样吧,有兴趣自己去修改

    2.无疑又增加了内存开销

    3.这是是我最不愿意的事情

      影响了printf一开始使用的中断发送

      因为一开始是不停的插入一个数据,然后中断发出去

      现在不可以这样了,还需要想办法呀

      需要一次性得到printf发送的内容,然后填充到环形队列里面.............

      真不好搞的话,还是用 sprintf 把,把数据序列化到一个数组里面,然后

      发送的数据个数 = sprintf(数组,XXXXXXX)

      PutData(&Uart1rb,NULL,数组,发送的数据个数);//数据写入环形队列
      SendCount[0] = 发送的数据个数;//这次发送的数据个数
      PutData(&Uart1rbManage,NULL,SendCount,1);//数据写入环形队列,记录这次要发送的数据个数

  • 相关阅读:
    转:为什么要有Spring?
    转:jsp与servlet的区别与联系
    转 原生js canvas实现苹果电脑mac OS窗口最小化效果
    JavaFX
    salesforce零基础学习(九十八)Type浅谈
    Salesforce LWC学习(十七) 前端知识之 onclick & onblur & onmousedown
    salesforce零基础学习(九十七)Event / Task 针对WhoId的浅谈
    salesforce零基础学习(九十六)Platform Event浅谈
    Salesforce LWC学习(十六) Validity 在form中的使用浅谈
    Salesforce LWC学习(十五) Async 以及 Picklist 公用方法的实现
  • 原文地址:https://www.cnblogs.com/yangfengwu/p/11769059.html
Copyright © 2020-2023  润新知