找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4467|回復: 24
收起左側(cè)

51單片機Uart與RGB兼容性問題

[復制鏈接]
ID:1071654 發(fā)表于 2023-9-16 17:40 | 顯示全部樓層 |閱讀模式
50黑幣
單片機STC89C52RC,晶振采用24MHZ,波特率9600,當前問題是:
1、把RGB()函數(shù)放在主函數(shù)while(1)里面后,雖然在串口助手看到有收到指令,指令所對應動作無法被執(zhí)行
2、注釋主函數(shù)中的RGB()函數(shù)后,先發(fā)指令1-6能收到且執(zhí)行,再發(fā)送指令9后,RGB燈正常,這時候發(fā)送1-6指令,概率性打斷RGB執(zhí)行對應指令
為什么RGB()運行的同時Uart指令無法識別呢?就算去掉RGB()中的Delay()函數(shù),看到的現(xiàn)象跟問題2一致。
感謝各位大神解答,感激不盡。!

#include <REGX52.H>
#include "UART.H"
#include "MotorDrive.H"
#include "INTRINS.H"    //包含nop指令頭文件
#include "Delay.H"
#include "Timer0.H"

#define nop  _nop_();
sbit DIN=P2^6;     //定義信號輸出DIN
unsigned char Compare,Compare1,Compare2,Compare3;
unsigned char Counter,Counter1,Counter2,Counter3;
unsigned int IC=2;              //控制TM1804個數(shù)
unsigned int LED_PX;            //像素點數(shù)
unsigned char PWM=255;          //TM1804灰度數(shù)據(jù)
unsigned char Rda,Gda,Bda;      //R、G、B灰度數(shù)據(jù)
unsigned char bdata LED_data;   //可位操作的數(shù)據(jù)發(fā)送暫存變量聲明

sbit bit0=LED_data^0;           //被發(fā)送的數(shù)據(jù)各位定義
sbit bit1=LED_data^1;
sbit bit2=LED_data^2;
sbit bit3=LED_data^3;
sbit bit4=LED_data^4;
sbit bit5=LED_data^5;
sbit bit6=LED_data^6;
sbit bit7=LED_data^7;
bit flag=0;

sbit L298N_ENA=P1^4;
sbit L298N_ENB=P1^5;
sbit L298N_ENA1=P1^1;
sbit L298N_ENB1=P0^2;

bit gb_RGB=0;
bit gbRI=0;

unsigned char Data;

void send_data_0()        //發(fā)送0碼函數(shù),規(guī)格書體現(xiàn)低速模式高電平700ns,周期2.5us
{
        //示波器實際測試高1uS,周期4.5uS
                DIN=1;
                _nop_();
                DIN=0;
}


void send_data_1()        //發(fā)送1碼函數(shù),規(guī)格書體現(xiàn)低速模式高電平1800ns,周期2.5us   
{
        //示波器實際測試高1.5uS,周期6uS
                DIN=1;
                _nop_();_nop_();
                DIN=0;
}

void send_data(unsigned char DATA1)        //發(fā)送1個字節(jié)數(shù)據(jù),高位先發(fā)               
{
LED_data=DATA1;                          
if(bit7)        send_data_1();        else send_data_0();
if(bit6)        send_data_1();        else send_data_0();
if(bit5)        send_data_1();        else send_data_0();
if(bit4)        send_data_1();        else send_data_0();
if(bit3)        send_data_1();        else send_data_0();
if(bit2)        send_data_1();        else send_data_0();
if(bit1)        send_data_1();        else send_data_0();
if(bit0)        send_data_1();        else send_data_0();
}

void send_px()        //發(fā)送1幀數(shù)據(jù)
{
unsigned int i;
for(i=0;i<LED_PX;i++)
  {
   send_data(Rda);             //發(fā)送R灰度數(shù)據(jù)
   send_data(Gda);             //發(fā)送G灰度數(shù)據(jù)
   send_data(Bda);             //發(fā)送B灰度數(shù)據(jù)
  }
}


void RGB()        //RGB函數(shù)
{
unsigned char i;
LED_PX=IC;                          //像素點數(shù)等于TM1804個數(shù)
Rda=Gda=Bda=0;                      //R、G、B灰度數(shù)據(jù)復位清零

   for(i=0;i<PWM;i++)          //紅色漸亮  
    {
     Rda=i;              //灰度計算
     send_px();          //發(fā)送灰度數(shù)據(jù)
     Delay(10);          //復位延時
    }
     for(i=0;i<PWM;i++)  //紅色漸滅,綠色漸亮
      {
       Gda=i;
       Rda=PWM-i;  //灰度計算
       send_px();  //發(fā)送灰度數(shù)據(jù)
       Delay(10);  //復位延時
      }
     for(i=0;i<PWM;i++)  //綠色漸滅,藍色漸亮
      {
       Bda=i;           
       Gda=PWM-i;  //灰度計算
       send_px();  //發(fā)送灰度數(shù)據(jù)       
       Delay(10);  //復位延時
      }
     for(i=0;i<PWM;i++)  //藍色漸滅,紅色漸亮
      {
       Rda=i;
       Bda=PWM-i;  //灰度計算
       send_px();  //發(fā)送灰度數(shù)據(jù)
       Delay(10);  //復位延時
      }
}

void main()
{
        UART_Init();
        L298N_ENA=1;
        L298N_ENB=1;
        L298N_ENA1=1;
        L298N_ENB1=1;
        while(1)
        {
//                RGB();
                if(Data==0)StopIt();        //停止
                if(Data==1)Forward();        //直行
                if(Data==2)BackOff();        //后退
                if(Data==3)TurnLeft();        //左轉(zhuǎn)
                if(Data==4)TurnRight();        //右轉(zhuǎn)
                if(Data==5)TurnLeftCircle();        //左轉(zhuǎn)彎
                if(Data==6)TurnRightCircle();        //右轉(zhuǎn)彎
                if(Data==9)RGB();                //RGB
                }
        }
void UART_Routine() interrupt 4    //串口中斷
{
gbRI=1;       
if(RI==1)   //允許單片機接收數(shù)據(jù)
{
        Data=SBUF;                   //讀取數(shù)據(jù)
        UART_SendByte(SBUF);  //將接收到的數(shù)據(jù)發(fā)回串口
        RI=0;  //接收標志位清0 軟件復位
}
}


最佳答案

相關帖子

回復

使用道具 舉報

ID:161164 發(fā)表于 2023-9-16 17:40 | 顯示全部樓層
wen1989jun 發(fā)表于 2023-9-25 09:41
定時器10mS的設置不太行哦,電機會有卡頓。
現(xiàn)在還是卡在沒辦法同時用,我繼續(xù)找找問題

不要用delay
  1. void RGB()        //RGB函數(shù)
  2. {
  3.         static unsigned char i=0, j=0;
  4.         static unsigned int DelayCnt = 0;
  5.         LED_PX=IC;                          //像素點數(shù)等于TM1804個數(shù)
  6.         if(DelayCnt++>=1000)
  7.         {
  8.                 DelayCnt=0;
  9.                 switch(j)
  10.                 {
  11.                 case 0:
  12.                         Rda=Gda=Bda=0;                      //R、G、B灰度數(shù)據(jù)復位清零
  13.                         j++;
  14.                         break;
  15.                 case 1:
  16.                         Rda=i;              //灰度計算
  17.                         if(++i>=PWM)
  18.                         {
  19.                                 i=0;
  20.                                 j++;
  21.                         }
  22.                         break;
  23.                 case 2:
  24.                         Gda=i;
  25.                         Rda=PWM-i;  //灰度計算
  26.                         if(++i>=PWM)
  27.                         {
  28.                                 i=0;
  29.                                 j++;
  30.                         }
  31.                         break;
  32.                 case 3:
  33.                         Bda=i;
  34.                         Gda=PWM-i;  //灰度計算
  35.                         if(++i>=PWM)
  36.                         {
  37.                                 i=0;
  38.                                 j++;
  39.                         }
  40.                         break;
  41.                 case 4:
  42.                         Rda=i;
  43.                         Bda=PWM-i;  //灰度計算
  44.                         if(++i>=PWM)
  45.                         {
  46.                                 i=0;
  47.                                 j++;
  48.                         }
  49.                         break;
  50.                 }
  51.                 send_px();          //發(fā)送灰度數(shù)據(jù)
  52.         }
  53. }
復制代碼
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-18 13:59 | 顯示全部樓層
自頂下,附件為51控制TM1804_RGB視頻

51控制TM1804_RGB.zip

16.9 MB, 下載次數(shù): 5

回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-18 17:03 | 顯示全部樓層
自頂下,感謝各位大神答疑!
回復

使用道具 舉報

ID:1092816 發(fā)表于 2023-9-19 11:40 | 顯示全部樓層
串口數(shù)據(jù)接收部分位于UART_Routine()函數(shù)中的串口中斷中。這意味著當該中斷被觸發(fā)時,會執(zhí)行UART_Routine()函數(shù)來接收串口數(shù)據(jù),并執(zhí)行相應的動作。

問題1:
將RGB()函數(shù)放在主函數(shù)while(1)循環(huán)內(nèi)部時,在執(zhí)行RGB()函數(shù)期間,由于沒有執(zhí)行完畢,此時可能無法及時觸發(fā)串口中斷來接收指令。因此,指令所對應的動作無法被執(zhí)行。你可以嘗試在RGB()函數(shù)執(zhí)行完畢后再進行串口指令的接收和執(zhí)行。

問題2:
這可能是由于程序運行時使用了中斷,同時存在幾個中斷源時,可能導致中斷優(yōu)先級出現(xiàn)問題。為了解決此問題,可以嘗試:
1. 在主函數(shù)中加入全局變量flag并初始化為0。
2. 將RGB()函數(shù)移到主函數(shù)的while循環(huán)之外。
3. 主函數(shù)中加入一個條件語句判斷,如果flag等于0,則執(zhí)行RGB()函數(shù);否則執(zhí)行串口指令的接收和執(zhí)行。

在RGB()函數(shù)執(zhí)行期間,flag會被設置為非零值,避免概率性打斷RGB燈執(zhí)行對應指令的問題。當RGB()函數(shù)執(zhí)行完畢后,flag會重新置零,再次執(zhí)行串口指令的接收和執(zhí)行。
回復

使用道具 舉報

ID:844772 發(fā)表于 2023-9-19 14:35 | 顯示全部樓層
好細的電源線啊,是用來兩套電源嗎?程序沒啥問題,就看看電源功率夠不夠了。
回復

使用道具 舉報

ID:404160 發(fā)表于 2023-9-19 14:55 | 顯示全部樓層
        Data=SBUF;                   //讀取數(shù)據(jù)
        UART_SendByte(SBUF);  //將接收到的數(shù)據(jù)發(fā)回串口
改成
        Data=SBUF;                   //讀取數(shù)據(jù)
        UART_SendByte(Data);  //將接收到的數(shù)據(jù)發(fā)回串口
試試
回復

使用道具 舉報

ID:161164 發(fā)表于 2023-9-19 17:47 | 顯示全部樓層
因為用了for循環(huán)+阻塞式延時
先辦法不用for循環(huán)和阻塞式延時來達到同樣效果

回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-19 18:30 | 顯示全部樓層
飛云居士 發(fā)表于 2023-9-19 14:55
Data=SBUF;                   //讀取數(shù)據(jù)
        UART_SendByte(SBUF);  //將接收到的數(shù)據(jù)發(fā)回 ...

按照您提供的方法驗證了,串口助手看到有收到指令,但在執(zhí)行RGB()函數(shù)中,其他指令依然不識別;發(fā)指令9執(zhí)行了RGB(),再發(fā)指令9,居然也不識別。
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-19 18:34 | 顯示全部樓層
glinfei 發(fā)表于 2023-9-19 14:35
好細的電源線啊,是用來兩套電源嗎?程序沒啥問題,就看看電源功率夠不夠了。

電源線由兩個18650電池自帶的線供電,雙電池,給電機升壓是SX1308_12V,當單電池供電,L298N使能時候確實有概率會導致供電不足,雙電池驗證多次均沒問題。
我在想單電池時候是不是由于升壓IC前端電容容量不夠?qū)е码姵剡M入了放電過流保護?
回復

使用道具 舉報

ID:844772 發(fā)表于 2023-9-20 09:07 | 顯示全部樓層
wen1989jun 發(fā)表于 2023-9-19 18:34
電源線由兩個18650電池自帶的線供電,雙電池,給電機升壓是SX1308_12V,當單電池供電,L298N使能時候確實 ...

我沒看到你的用電功率情況,用了什么高級電機要12V啊,還有能否先不用升壓模塊試試?這種小車好多問題就不在程序上。
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-20 09:19 | 顯示全部樓層
glinfei 發(fā)表于 2023-9-20 09:07
我沒看到你的用電功率情況,用了什么高級電機要12V啊,還有能否先不用升壓模塊試試?這種小車好多問題就 ...

單電池概率性被拉死情況目前沒有去排查,電機用的12V_600轉(zhuǎn)的N20。
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-20 09:31 | 顯示全部樓層
cjc1029 發(fā)表于 2023-9-19 11:40
串口數(shù)據(jù)接收部分位于UART_Routine()函數(shù)中的串口中斷中。這意味著當該中斷被觸發(fā)時,會執(zhí)行UART_Routine() ...

問題1:確認在RGB()執(zhí)行完成之后能收到其他指令,也能被執(zhí)行。我只是懷疑難道是因為RGB_DIN這個IO口翻轉(zhuǎn)太快,Uart就收不到指令啦?
問題2:按照您提供的方法驗證了,還是不行;RGB()執(zhí)行期間,Uart收到的指令無法被執(zhí)行。
另外,您說的同時存在幾個中斷時候確認會導致RGB()無法正常運行,RGB燈異常閃爍。僅僅加了如下代碼并打開了ET0=1;就會導致這個情況發(fā)生,也沒太搞懂是個啥情況。
void Timer0_Init()        //100微秒@24MHz
{
        TMOD &= 0xF0;                //設置定時器模式
        TMOD |= 0x01;                //設置定時器模式
        TL0 = 0x38;                //設置定時初值
        TH0 = 0xFF;                //設置定時初值
        TF0 = 0;                //清除TF0標志
        TR0 = 1;                //定時器0開始計時
        ET0=0;        //1為允許T0中斷,0為禁止
        EA=1;        //開啟總中斷
        PT0=1;        //中斷優(yōu)先級控制
}

void Timer0_Routine() interrupt 1
{
        TL0=0x38;  //設置定時初值
        TH0=0xFF;  //設置定時初值
        Counter++;
        Counter%=100;                //計數(shù)值變化范圍限制在0~99
        Counter1++;
        Counter1%=100;        //計數(shù)值變化范圍限制在0~99
        Counter2++;
        Counter2%=100;        //計數(shù)值變化范圍限制在0~99
        Counter3++;
        Counter3%=100;        //計數(shù)值變化范圍限制在0~99
        if(Counter<Compare)
        {
                L298N_ENA=1;
        }
        else
        {
                L298N_ENA=0;
        }
        if(Counter1<Compare1)
        {
                L298N_ENB=1;
        }
        else
        {
                L298N_ENB=0;
        }
        if(Counter2<Compare2)
        {
                L298N_ENA1=1;
        }
        else
        {
                L298N_ENA1=0;
        }
        if(Counter3<Compare3)
        {
                L298N_ENB1=1;
        }
        else
        {
                L298N_ENB1=0;
        }
}
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-20 09:39 | 顯示全部樓層
lkc8210 發(fā)表于 2023-9-19 17:47
因為用了for循環(huán)+阻塞式延時
先辦法不用for循環(huán)和阻塞式延時來達到同樣效果

謝謝您的指導,我加油。!
回復

使用道具 舉報

ID:844772 發(fā)表于 2023-9-20 16:08 | 顯示全部樓層
wen1989jun 發(fā)表于 2023-9-20 09:31
問題1:確認在RGB()執(zhí)行完成之后能收到其他指令,也能被執(zhí)行。我只是懷疑難道是因為RGB_DIN這個IO口翻轉(zhuǎn) ...

定時器0設的太短了,對于N20電機的PWM沒必要這么快,因為2812的控制對時刻要求特別高,老是中斷很影響效果,當然在RGB()運行期間只要中斷都會影響效果,2812控制時刻是1微秒級的;
RGB()執(zhí)行期間當然 ,不能執(zhí)行指令。這是你程序決定的,但執(zhí)行完就應該可以啊。
還有我有點拿不準,4個N20啟動功率差不多6W,如果加10個2812總功率超過10W了,升壓模塊應付的了嗎?
回復

使用道具 舉報

ID:526543 發(fā)表于 2023-9-20 17:24 | 顯示全部樓層
可能與串口中斷和RGB函數(shù)之間的并發(fā)執(zhí)行有關
回復

使用道具 舉報

ID:1092816 發(fā)表于 2023-9-20 17:50 | 顯示全部樓層
先排除硬件,如果單一模塊運行沒有問題,對于資源小的單片機,你要優(yōu)化的是程序的架構(gòu),全部放while里不合適。你RGB里面的for也是耗CPU的,降低刷新頻率試一下。
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-21 10:09 | 顯示全部樓層
123456ZXC1 發(fā)表于 2023-9-20 17:24
可能與串口中斷和RGB函數(shù)之間的并發(fā)執(zhí)行有關

兄弟,展開說說看
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-21 14:35 | 顯示全部樓層
glinfei 發(fā)表于 2023-9-20 16:08
定時器0設的太短了,對于N20電機的PWM沒必要這么快,因為2812的控制對時刻要求特別高,老是中斷很影響效 ...

定時器0當前設置的是100us,這個設置多少合適呢?
RGB控制用的是TM1804哦,用了2Pcs,各控制了7個RGB燈,這兩個IC由ETA的DCDC供電
4個N20電機由2個L298N控制,2個L298N由兩路SX1308供電,電源來自2個2550mAh的18650電池
回復

使用道具 舉報

ID:1094164 發(fā)表于 2023-9-21 15:21 | 顯示全部樓層
電源線太細是不是也有點關系啊
回復

使用道具 舉報

ID:844772 發(fā)表于 2023-9-22 09:13 | 顯示全部樓層
wen1989jun 發(fā)表于 2023-9-21 14:35
定時器0當前設置的是100us,這個設置多少合適呢?
RGB控制用的是TM1804哦,用了2Pcs,各控制了7個RGB燈 ...

1,電機有慣性的,幾十Hz,也就是10毫秒級就行了;
2. 給機械部分供電一般只降壓,沒看到電路按你說的理論上確實可以,但實際會出現(xiàn)各種莫名狀況;
3.我覺得程序可以達到目的,雖然優(yōu)化空間較大,但不是主要問題。
4.另外,遙控影響燈效和燈效期間不執(zhí)行命令這是程序問題,但也不大影響使用。
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-22 16:13 | 顯示全部樓層
cjc1029 發(fā)表于 2023-9-20 17:50
先排除硬件,如果單一模塊運行沒有問題,對于資源小的單片機,你要優(yōu)化的是程序的架構(gòu),全部放while里不合 ...

單一模塊是可以正常工作的,現(xiàn)在就是放在一起沒辦法同時執(zhí)行。
降低刷新率是否就是修改RGB()里面的Delay()的值?
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-23 09:32 | 顯示全部樓層
流利說你好 發(fā)表于 2023-9-21 15:21
電源線太細是不是也有點關系啊

這個應該沒太大關系了,電源只是影響是否工作,工作是否穩(wěn)定的吧
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-25 09:41 | 顯示全部樓層
glinfei 發(fā)表于 2023-9-22 09:13
1,電機有慣性的,幾十Hz,也就是10毫秒級就行了;
2. 給機械部分供電一般只降壓,沒看到電路按你說的理 ...

定時器10mS的設置不太行哦,電機會有卡頓。
現(xiàn)在還是卡在沒辦法同時用,我繼續(xù)找找問題
回復

使用道具 舉報

ID:1071654 發(fā)表于 2023-9-25 11:44 | 顯示全部樓層

使用了您提供的代碼,驗證RGB()和其他指令不沖突均可運行,但也表現(xiàn)出一個問題:
不管把RGB()函數(shù)放進主函數(shù)while(1)里面,還是放在主函數(shù)if()里面,RGB()函數(shù)均執(zhí)行一次就結(jié)束了
不管咋說,真的非常感謝您,我自己再研究學習下,再次感謝您。!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復 返回頂部 返回列表