標(biāo)題: 51單片機(jī)Uart與RGB兼容性問(wèn)題 [打印本頁(yè)]

作者: wen1989jun    時(shí)間: 2023-9-16 17:40
標(biāo)題: 51單片機(jī)Uart與RGB兼容性問(wèn)題
單片機(jī)STC89C52RC,晶振采用24MHZ,波特率9600,當(dāng)前問(wèn)題是:
1、把RGB()函數(shù)放在主函數(shù)while(1)里面后,雖然在串口助手看到有收到指令,指令所對(duì)應(yīng)動(dòng)作無(wú)法被執(zhí)行
2、注釋主函數(shù)中的RGB()函數(shù)后,先發(fā)指令1-6能收到且執(zhí)行,再發(fā)送指令9后,RGB燈正常,這時(shí)候發(fā)送1-6指令,概率性打斷RGB執(zhí)行對(duì)應(yīng)指令
為什么RGB()運(yùn)行的同時(shí)Uart指令無(wú)法識(shí)別呢?就算去掉RGB()中的Delay()函數(shù),看到的現(xiàn)象跟問(wè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;     //定義信號(hào)輸出DIN
unsigned char Compare,Compare1,Compare2,Compare3;
unsigned char Counter,Counter1,Counter2,Counter3;
unsigned int IC=2;              //控制TM1804個(gè)數(shù)
unsigned int LED_PX;            //像素點(diǎn)數(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ī)格書(shū)體現(xiàn)低速模式高電平700ns,周期2.5us
{
        //示波器實(shí)際測(cè)試高1uS,周期4.5uS
                DIN=1;
                _nop_();
                DIN=0;
}


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

void send_data(unsigned char DATA1)        //發(fā)送1個(gè)字節(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;                          //像素點(diǎn)數(shù)等于TM1804個(gè)數(shù)
Rda=Gda=Bda=0;                      //R、G、B灰度數(shù)據(jù)復(fù)位清零

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

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)   //允許單片機(jī)接收數(shù)據(jù)
{
        Data=SBUF;                   //讀取數(shù)據(jù)
        UART_SendByte(SBUF);  //將接收到的數(shù)據(jù)發(fā)回串口
        RI=0;  //接收標(biāo)志位清0 軟件復(fù)位
}
}



作者: lkc8210    時(shí)間: 2023-9-16 17:40
wen1989jun 發(fā)表于 2023-9-25 09:41
定時(shí)器10mS的設(shè)置不太行哦,電機(jī)會(huì)有卡頓。
現(xiàn)在還是卡在沒(méi)辦法同時(shí)用,我繼續(xù)找找問(wèn)題

不要用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;                          //像素點(diǎn)數(shù)等于TM1804個(gè)數(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ù)復(fù)位清零
  13.                         j++;
  14.                         break;
  15.                 case 1:
  16.                         Rda=i;              //灰度計(jì)算
  17.                         if(++i>=PWM)
  18.                         {
  19.                                 i=0;
  20.                                 j++;
  21.                         }
  22.                         break;
  23.                 case 2:
  24.                         Gda=i;
  25.                         Rda=PWM-i;  //灰度計(jì)算
  26.                         if(++i>=PWM)
  27.                         {
  28.                                 i=0;
  29.                                 j++;
  30.                         }
  31.                         break;
  32.                 case 3:
  33.                         Bda=i;
  34.                         Gda=PWM-i;  //灰度計(jì)算
  35.                         if(++i>=PWM)
  36.                         {
  37.                                 i=0;
  38.                                 j++;
  39.                         }
  40.                         break;
  41.                 case 4:
  42.                         Rda=i;
  43.                         Bda=PWM-i;  //灰度計(jì)算
  44.                         if(++i>=PWM)
  45.                         {
  46.                                 i=0;
  47.                                 j++;
  48.                         }
  49.                         break;
  50.                 }
  51.                 send_px();          //發(fā)送灰度數(shù)據(jù)
  52.         }
  53. }
復(fù)制代碼

作者: wen1989jun    時(shí)間: 2023-9-18 13:59
自頂下,附件為51控制TM1804_RGB視頻

51控制TM1804_RGB.zip

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


作者: wen1989jun    時(shí)間: 2023-9-18 17:03
自頂下,感謝各位大神答疑!
作者: cjc1029    時(shí)間: 2023-9-19 11:40
串口數(shù)據(jù)接收部分位于UART_Routine()函數(shù)中的串口中斷中。這意味著當(dāng)該中斷被觸發(fā)時(shí),會(huì)執(zhí)行UART_Routine()函數(shù)來(lái)接收串口數(shù)據(jù),并執(zhí)行相應(yīng)的動(dòng)作。

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

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

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

作者: glinfei    時(shí)間: 2023-9-19 14:35
好細(xì)的電源線(xiàn)啊,是用來(lái)兩套電源嗎?程序沒(méi)啥問(wèn)題,就看看電源功率夠不夠了。
作者: 飛云居士    時(shí)間: 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ā)回串口
試試
作者: lkc8210    時(shí)間: 2023-9-19 17:47
因?yàn)橛昧薴or循環(huán)+阻塞式延時(shí)
先辦法不用for循環(huán)和阻塞式延時(shí)來(lái)達(dá)到同樣效果


作者: wen1989jun    時(shí)間: 2023-9-19 18:30
飛云居士 發(fā)表于 2023-9-19 14:55
Data=SBUF;                   //讀取數(shù)據(jù)
        UART_SendByte(SBUF);  //將接收到的數(shù)據(jù)發(fā)回 ...

按照您提供的方法驗(yàn)證了,串口助手看到有收到指令,但在執(zhí)行RGB()函數(shù)中,其他指令依然不識(shí)別;發(fā)指令9執(zhí)行了RGB(),再發(fā)指令9,居然也不識(shí)別。
作者: wen1989jun    時(shí)間: 2023-9-19 18:34
glinfei 發(fā)表于 2023-9-19 14:35
好細(xì)的電源線(xiàn)啊,是用來(lái)兩套電源嗎?程序沒(méi)啥問(wèn)題,就看看電源功率夠不夠了。

電源線(xiàn)由兩個(gè)18650電池自帶的線(xiàn)供電,雙電池,給電機(jī)升壓是SX1308_12V,當(dāng)單電池供電,L298N使能時(shí)候確實(shí)有概率會(huì)導(dǎo)致供電不足,雙電池驗(yàn)證多次均沒(méi)問(wèn)題。
我在想單電池時(shí)候是不是由于升壓IC前端電容容量不夠?qū)е码姵剡M(jìn)入了放電過(guò)流保護(hù)?
作者: glinfei    時(shí)間: 2023-9-20 09:07
wen1989jun 發(fā)表于 2023-9-19 18:34
電源線(xiàn)由兩個(gè)18650電池自帶的線(xiàn)供電,雙電池,給電機(jī)升壓是SX1308_12V,當(dāng)單電池供電,L298N使能時(shí)候確實(shí) ...

我沒(méi)看到你的用電功率情況,用了什么高級(jí)電機(jī)要12V啊,還有能否先不用升壓模塊試試?這種小車(chē)好多問(wèn)題就不在程序上。
作者: wen1989jun    時(shí)間: 2023-9-20 09:19
glinfei 發(fā)表于 2023-9-20 09:07
我沒(méi)看到你的用電功率情況,用了什么高級(jí)電機(jī)要12V啊,還有能否先不用升壓模塊試試?這種小車(chē)好多問(wèn)題就 ...

單電池概率性被拉死情況目前沒(méi)有去排查,電機(jī)用的12V_600轉(zhuǎn)的N20。
作者: wen1989jun    時(shí)間: 2023-9-20 09:31
cjc1029 發(fā)表于 2023-9-19 11:40
串口數(shù)據(jù)接收部分位于UART_Routine()函數(shù)中的串口中斷中。這意味著當(dāng)該中斷被觸發(fā)時(shí),會(huì)執(zhí)行UART_Routine() ...

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

void Timer0_Routine() interrupt 1
{
        TL0=0x38;  //設(shè)置定時(shí)初值
        TH0=0xFF;  //設(shè)置定時(shí)初值
        Counter++;
        Counter%=100;                //計(jì)數(shù)值變化范圍限制在0~99
        Counter1++;
        Counter1%=100;        //計(jì)數(shù)值變化范圍限制在0~99
        Counter2++;
        Counter2%=100;        //計(jì)數(shù)值變化范圍限制在0~99
        Counter3++;
        Counter3%=100;        //計(jì)數(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;
        }
}
作者: wen1989jun    時(shí)間: 2023-9-20 09:39
lkc8210 發(fā)表于 2023-9-19 17:47
因?yàn)橛昧薴or循環(huán)+阻塞式延時(shí)
先辦法不用for循環(huán)和阻塞式延時(shí)來(lái)達(dá)到同樣效果

謝謝您的指導(dǎo),我加油!。
作者: glinfei    時(shí)間: 2023-9-20 16:08
wen1989jun 發(fā)表于 2023-9-20 09:31
問(wèn)題1:確認(rèn)在RGB()執(zhí)行完成之后能收到其他指令,也能被執(zhí)行。我只是懷疑難道是因?yàn)镽GB_DIN這個(gè)IO口翻轉(zhuǎn) ...

定時(shí)器0設(shè)的太短了,對(duì)于N20電機(jī)的PWM沒(méi)必要這么快,因?yàn)?812的控制對(duì)時(shí)刻要求特別高,老是中斷很影響效果,當(dāng)然在RGB()運(yùn)行期間只要中斷都會(huì)影響效果,2812控制時(shí)刻是1微秒級(jí)的;
RGB()執(zhí)行期間當(dāng)然 ,不能執(zhí)行指令。這是你程序決定的,但執(zhí)行完就應(yīng)該可以啊。
還有我有點(diǎn)拿不準(zhǔn),4個(gè)N20啟動(dòng)功率差不多6W,如果加10個(gè)2812總功率超過(guò)10W了,升壓模塊應(yīng)付的了嗎?
作者: 123456ZXC1    時(shí)間: 2023-9-20 17:24
可能與串口中斷和RGB函數(shù)之間的并發(fā)執(zhí)行有關(guān)
作者: cjc1029    時(shí)間: 2023-9-20 17:50
先排除硬件,如果單一模塊運(yùn)行沒(méi)有問(wèn)題,對(duì)于資源小的單片機(jī),你要優(yōu)化的是程序的架構(gòu),全部放while里不合適。你RGB里面的for也是耗CPU的,降低刷新頻率試一下。
作者: wen1989jun    時(shí)間: 2023-9-21 10:09
123456ZXC1 發(fā)表于 2023-9-20 17:24
可能與串口中斷和RGB函數(shù)之間的并發(fā)執(zhí)行有關(guān)

兄弟,展開(kāi)說(shuō)說(shuō)看
作者: wen1989jun    時(shí)間: 2023-9-21 14:35
glinfei 發(fā)表于 2023-9-20 16:08
定時(shí)器0設(shè)的太短了,對(duì)于N20電機(jī)的PWM沒(méi)必要這么快,因?yàn)?812的控制對(duì)時(shí)刻要求特別高,老是中斷很影響效 ...

定時(shí)器0當(dāng)前設(shè)置的是100us,這個(gè)設(shè)置多少合適呢?
RGB控制用的是TM1804哦,用了2Pcs,各控制了7個(gè)RGB燈,這兩個(gè)IC由ETA的DCDC供電
4個(gè)N20電機(jī)由2個(gè)L298N控制,2個(gè)L298N由兩路SX1308供電,電源來(lái)自2個(gè)2550mAh的18650電池
作者: 流利說(shuō)你好    時(shí)間: 2023-9-21 15:21
電源線(xiàn)太細(xì)是不是也有點(diǎn)關(guān)系啊
作者: glinfei    時(shí)間: 2023-9-22 09:13
wen1989jun 發(fā)表于 2023-9-21 14:35
定時(shí)器0當(dāng)前設(shè)置的是100us,這個(gè)設(shè)置多少合適呢?
RGB控制用的是TM1804哦,用了2Pcs,各控制了7個(gè)RGB燈 ...

1,電機(jī)有慣性的,幾十Hz,也就是10毫秒級(jí)就行了;
2. 給機(jī)械部分供電一般只降壓,沒(méi)看到電路按你說(shuō)的理論上確實(shí)可以,但實(shí)際會(huì)出現(xiàn)各種莫名狀況;
3.我覺(jué)得程序可以達(dá)到目的,雖然優(yōu)化空間較大,但不是主要問(wèn)題。
4.另外,遙控影響燈效和燈效期間不執(zhí)行命令這是程序問(wèn)題,但也不大影響使用。
作者: wen1989jun    時(shí)間: 2023-9-22 16:13
cjc1029 發(fā)表于 2023-9-20 17:50
先排除硬件,如果單一模塊運(yùn)行沒(méi)有問(wèn)題,對(duì)于資源小的單片機(jī),你要優(yōu)化的是程序的架構(gòu),全部放while里不合 ...

單一模塊是可以正常工作的,現(xiàn)在就是放在一起沒(méi)辦法同時(shí)執(zhí)行。
降低刷新率是否就是修改RGB()里面的Delay()的值?
作者: wen1989jun    時(shí)間: 2023-9-23 09:32
流利說(shuō)你好 發(fā)表于 2023-9-21 15:21
電源線(xiàn)太細(xì)是不是也有點(diǎn)關(guān)系啊

這個(gè)應(yīng)該沒(méi)太大關(guān)系了,電源只是影響是否工作,工作是否穩(wěn)定的吧
作者: wen1989jun    時(shí)間: 2023-9-25 09:41
glinfei 發(fā)表于 2023-9-22 09:13
1,電機(jī)有慣性的,幾十Hz,也就是10毫秒級(jí)就行了;
2. 給機(jī)械部分供電一般只降壓,沒(méi)看到電路按你說(shuō)的理 ...

定時(shí)器10mS的設(shè)置不太行哦,電機(jī)會(huì)有卡頓。
現(xiàn)在還是卡在沒(méi)辦法同時(shí)用,我繼續(xù)找找問(wèn)題
作者: wen1989jun    時(shí)間: 2023-9-25 11:44
lkc8210 發(fā)表于 2023-9-25 10:38
不要用delay

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




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1