久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 3260|回復: 17
打印 上一主題 下一主題
收起左側

51單片機Uart和定時器0同時使用問題

[復制鏈接]
回帖獎勵 200 黑幣 回復本帖可獲得 2 黑幣獎勵! 每人限 1 次
跳轉到指定樓層
樓主
ID:1071654 發表于 2023-8-19 15:13 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
如下為STC89C52單片機制作智能小車,藍牙遙控,紅外循跡均可單獨使用,兩個功能整合在一起時候藍牙遙控指令只有紅外循跡可使用了,其他指令小車不執行對應動作,請問代碼是哪里有問題,望指出,感謝!
1、懷疑藍牙發1-6時候,電機驅動并未使能,所以相應動作未執行,不太確認是否是Timer0定時器未工作原因?
2、我用Timer0做電機驅動使能控制,Timer1做Uart,可T0的中斷優先級比T1的要高,如何讓兩個同時用而不沖突呢?
3、另外,是否能在主函數給電機驅動定義變量,其他子函數,包括中斷都能調用呢?如下代碼有在主函數定義變量,同時在紅外循跡中也定義了相同變量,如不定義,無法編譯
以上問題,希望各位大神指點下思路。

主函數

#include <REGX52.H>
#include "UART.H"
#include "MotorDrive.H"
#include "Timer0.H"
#include "IR_Tracking.H"

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

extern unsigned char Compare,Compare1,Compare2,Compare3;
extern unsigned char Counter,Counter1,Counter2,Counter3;



void main()
{
        UART_Init();
        Timer0_Init();
//        L298N_ENA=1;
//        L298N_ENB=1;
//        L298N_ENA1=1;
//        L298N_ENB1=1;
        while(1)
        {
               
        }
}


void Timer0_Routine() interrupt 1
{
        TL0=0xA4;  //設置定時初值
        TH0=0xFF;  //設置定時初值
        Counter++;
        Counter%=100;                //計數值變化范圍限制在0~99
        Counter1++;
        Counter1%=100;        //計數值變化范圍限制在0~99
        Counter2++;
        Counter2%=100;        //計數值變化范圍限制在0~99
        Counter3++;
        Counter3%=100;        //計數值變化范圍限制在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;
        }
}

void UART_Routine() interrupt 4    //串口中斷
{         
unsigned char Data;
if(RI==1)   //允許單片機接收數據
{
        Data=SBUF;                   //讀取數據
        UART_SendByte(SBUF);  //將接收到的數據發回串口
        RI=0;  //接收標志位清0 軟件復位
switch(Data)
  {
        case 0:StopIt();                break;
        case 1:Forward();                break;
        case 2:BackOff();                break;
        case 3:TurnLeft();        break;
        case 4:TurnRight();        break;
        case 5:TurnLeftCircle();                break;
        case 6:TurnRightCircle();                break;
        case 7:IR_Tracking(); break;

  }
}
}



UART

#include <REGX52.H>

/**
*@brief  串口初始化9600bps@11.0592MHz
*@param  無
*retval  無
**/
void UART_Init()                //9600bps@11.0592MHz
{
        PCON &= 0x7F;                //波特率不倍速
        SCON = 0x50;                //8位數據,可變波特率
        TMOD &= 0x0F;                //清除定時器1模式位
        TMOD |= 0x20;                //設定定時器1為8位自動重裝方式
        TL1 = 0xFD;                //設定定時初值
        TH1 = 0xFD;                //設定定時器重裝值
        ET1 = 0;                //禁止定時器1中斷
        TR1 = 1;        //啟動定時器1
        EA        =1;
        ES        =1;
}

/**
*@brief  串口發送一個數據
*@param  Byte
*retval  無
*/

void UART_SendByte(unsigned char Byte)
{
        SBUF=Byte;
        while(TI==0);
        TI=0;
}

電機驅動

#include <REGX52.H>

sfr P4=0xe8;

sbit L298N_IN1        =P1^2;
sbit L298N_IN2        =P1^3;        //IN1&1N2是右前輪
sbit L298N_IN3        =P1^6;
sbit L298N_IN4        =P1^7;        //IN3&IN4是右后輪

sbit L298N_IN41        =P0^1;
sbit L298N_IN31        =P0^0;        //IN31&IN41是左前輪
sbit L298N_IN21        =P4^2;
sbit L298N_IN11        =P1^0;        //IN21&IN11是左后輪

void Forward()  //前進
{
                L298N_IN1=0;
                L298N_IN2=1;
                L298N_IN3=0;
                L298N_IN4=1;
                L298N_IN11=1;
                L298N_IN21=0;
                L298N_IN31=1;
                L298N_IN41=0;
}

void BackOff()        //后退
{

                L298N_IN1=1;
                L298N_IN2=0;
                L298N_IN3=1;
                L298N_IN4=0;
                L298N_IN11=0;
                L298N_IN21=1;
                L298N_IN31=0;
                L298N_IN41=1;
}

void TurnRight()        //右轉
{
                L298N_IN11=1;
                L298N_IN21=0;
                L298N_IN31=1;
                L298N_IN41=0;
}

void TurnRightCircle()        //右轉圈
{
                L298N_IN1=1;
                L298N_IN2=0;
                L298N_IN3=1;
                L298N_IN4=0;
                L298N_IN11=1;
                L298N_IN21=0;
                L298N_IN31=1;
                L298N_IN41=0;
}

void TurnLeft()        //左轉
{
                L298N_IN1=0;
                L298N_IN2=1;
                L298N_IN3=0;
                L298N_IN4=1;
        
}

void TurnLeftCircle()        //左轉圈
{
                L298N_IN1=0;
                L298N_IN2=1;
                L298N_IN3=0;
                L298N_IN4=1;
                L298N_IN11=0;
                L298N_IN21=1;
                L298N_IN31=0;
                L298N_IN41=1;
}

void StopIt()        //停止
{
                L298N_IN1=0;
                L298N_IN2=0;
                L298N_IN3=0;
                L298N_IN4=0;
                L298N_IN11=0;
                L298N_IN21=0;
                L298N_IN31=0;
                L298N_IN41=0;
}


Timer0

#include <REGX52.H>

void Timer0_Init()        //100微秒@11.0592MHz
{
        TMOD &= 0xF0;                //設置定時器模式
        TMOD |= 0x01;                //設置定時器模式
        TL0 = 0xA4;                //設置定時初值
        TH0 = 0xFF;                //設置定時初值
        TF0 = 0;                //清除TF0標志
        TR0 = 1;                //定時器0開始計時
        ET0=1;
        EA=1;
        PT0=1;
}




紅外循跡

#include <REGX52.H>
#include "MotorDrive.H"

sbit LM339_OUT1=P0^4;        //IR_1
sbit LM339_OUT2=P0^5;        //IR_2
sbit LM339_OUT3=P0^7;        //IR_3
sbit LM339_OUT4=P0^6;        //IR_4

unsigned char Compare,Compare1,Compare2,Compare3;
unsigned char Counter,Counter1,Counter2,Counter3;

void IR_Tracking()
{
        while(1)
        {
                if(LM339_OUT2==0&&LM339_OUT3==0)
{        
                        Compare=8;
                        Compare1=8;
                        Compare2=8;
                        Compare3=8;
                        Forward();
}

                if(LM339_OUT2==1&&LM339_OUT3==1)
{
                        StopIt();
}
               
                if(LM339_OUT2==1&&LM339_OUT3==0)
{
                        Compare=50;
                        Compare1=50;
                        TurnLeftCircle();
}
                if(LM339_OUT2==0&&LM339_OUT3==1)
{
                        Compare2=50;
                        Compare3=50;
                        TurnRightCircle();
}

        }

                }






分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

來自 4#
ID:123289 發表于 2023-8-21 09:27 | 只看該作者
2、我用Timer0做電機驅動使能控制,Timer1做Uart,可T0的中斷優先級比T1的要高,如何讓兩個同時用而不沖突呢?
說明你很聰明,發現問題了。
解決的方案:
讓T0的中斷服務程序運行時間,低于串行CLK的半個周期,如波特率=2400,周期=417us。
如何辦到:
在【T0的中斷服務程序】中,只做一個標記【ZDT0=1】,表示發生了中斷。其它需要處理的事項,放在主程序去做。主程序識別到【ZDT0=1】,就處理中斷事件,處理完成后復柆【ZDT0=0】。
這樣就不會影響T1中斷了。
明白了這個道理之后,記住【這是精華】:所有的【中斷服務程序】都要盡可能的短。方法:【中斷服務程序】只做標記,不做中斷事件處理(除非萬不得矣),中斷事件的處理,盡可能放在主程序中去做!

評分

參與人數 1黑幣 +5 收起 理由
wen1989jun + 5

查看全部評分

回復

使用道具 舉報

來自 10#
ID:1073939 發表于 2023-8-24 12:01 | 只看該作者
wen1989jun 發表于 2023-8-23 18:04
經過4樓大神的指導,現在把紅外循跡代碼放到主程序來了,把Uart里面中斷處理事情放在主程序來了之后,實現 ...
當紅外循跡指令發給MCU后,其他指令MCU能識別及返回,但不執行相應的動作了

只需要把IR_Tracking()函數中的“while(1)”這行注釋就可以了。

你代碼還有些問題。
Data這個全局變量表示最后收到的數據,還需要增加一個全局變量表示這數據是否已經處理。
  1. bit gbTrack=0;
  2. bit gbRI=0;
  3. void main()
  4. {
  5.         UART_Init();
  6.         Timer0_Init();
  7.         Compare = Compare1 = Compare2 = Compare3 = 20;
  8.         while(1)
  9.         {
  10.                 if(gbTrack)
  11.                         IR_Tracking();//循跡
  12.                 if(gbRI)//有新的串口數據 在串口接收中斷中加入gbRI=1;
  13.                 {
  14.                         gbRI=0;//新的串口數據已處理
  15.                         gbTrack=0;//除循跡指令外,其它指令不循跡
  16.                         if(Data == 7)
  17.                                 gbTrack=1;//收到循跡指令
  18.                         else if(Data == 0)
  19.                                 StopIt();
  20.                         else if(Data == 1)
  21.                         {
  22.                                 Compare = Compare1 = Compare2 = Compare3 = 20;
  23.                                 Forward();
  24.                         }
  25.                         else if(Data == 2)
  26.                         {
  27.                                 Compare = Compare1 = Compare2 = Compare3 = 20;
  28.                                 BackOff();
  29.                         }
  30.                 }
  31.         }
  32. }
復制代碼


回復

使用道具 舉報

沙發
ID:1071654 發表于 2023-8-19 15:54 | 只看該作者
自己先頂下帖子
回復

使用道具 舉報

板凳
ID:1071654 發表于 2023-8-21 09:23 | 只看該作者
自頂下,求大神解惑
回復

使用道具 舉報

5#
ID:277550 發表于 2023-8-21 10:16 | 只看該作者
主要原因是在中斷中,語句耗時太多。

~
回復

使用道具 舉報

6#
ID:1071654 發表于 2023-8-21 15:16 | 只看該作者
devcang 發表于 2023-8-21 10:16
主要原因是在中斷中,語句耗時太多。

~

能展開詳細說說么,我來驗證下
回復

使用道具 舉報

7#
ID:1071654 發表于 2023-8-21 15:51 | 只看該作者
yzwzfyz 發表于 2023-8-21 09:27
2、我用Timer0做電機驅動使能控制,Timer1做Uart,可T0的中斷優先級比T1的要高,如何讓兩個同時用而不沖突 ...

Uart中斷做標志位,主程序做識別,之前中斷里面的Switch可以放在主程序里面去做即可對么?

其它需要處理的事項,放在主程序去做。主程序識別到【ZDT0=1】,就處理中斷事件,處理完成后復柆【ZDT0=0】。
通過這句話我又感覺不能用Switch去做了

真是抱歉,C語言和單片機都是初學,還有很多不理解的地方,一會兒我去試試寫代碼驗證看看,還是非常感謝您的解答!!
回復

使用道具 舉報

8#
ID:1071654 發表于 2023-8-23 18:04 | 只看該作者
經過4樓大神的指導,現在把紅外循跡代碼放到主程序來了,把Uart里面中斷處理事情放在主程序來了之后,實現了藍牙遙控小車及紅外循跡功能了。
出現了一個新的問題,當紅外循跡指令發給MCU后,其他指令MCU能識別及返回,但不執行相應的動作了

#include <REGX52.H>
#include <Timer0.H>
#include "UART.H"
#include "MotorDrive.H"

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

sbit LM339_OUT1=P0^4;        //IR_1
sbit LM339_OUT2=P0^5;        //IR_2
sbit LM339_OUT3=P0^7;        //IR_3
sbit LM339_OUT4=P0^6;        //IR_4

unsigned char Compare,Compare1,Compare2,Compare3;
unsigned char Counter,Counter1,Counter2,Counter3;

unsigned char Data;

void IR_Tracking()
{
        while(1)
        {
                if(LM339_OUT2==0&&LM339_OUT3==0)
{       
                        Compare=8;
                        Compare1=8;
                        Compare2=8;
                        Compare3=8;
                        Forward();
}

                if(LM339_OUT2==1&&LM339_OUT3==1)
{
                        StopIt();
}
               
                if(LM339_OUT2==1&&LM339_OUT3==0)
{
                        Compare=50;
                        Compare1=50;
                        TurnLeftCircle();
}
                if(LM339_OUT2==0&&LM339_OUT3==1)
{
                        Compare2=50;
                        Compare3=50;
                        TurnRightCircle();
}

        }

                }

void main()
{
        UART_Init();
        Timer0_Init();
        Compare=20;
        Compare1=20;
        Compare2=20;
        Compare3=20;
        while(1)
        {
                if(Data==1)
                {
                        Compare=20;
                        Compare1=20;
                        Compare2=20;
                        Compare3=20;
                        Forward();
                }
                if(Data==2)
                {
                        Compare=20;
                        Compare1=20;
                        Compare2=20;
                        Compare3=20;
                        BackOff();
                }
                if(Data==7)
                {
                        IR_Tracking();
                }
                if(Data==0)
                {
                        StopIt();
                }
        }
}


void Timer0_Routine() interrupt 1
{
        TL0=0xA4;  //設置定時初值
        TH0=0xFF;  //設置定時初值
        Counter++;
        Counter%=100;                //計數值變化范圍限制在0~99
        Counter1++;
        Counter1%=100;        //計數值變化范圍限制在0~99
        Counter2++;
        Counter2%=100;        //計數值變化范圍限制在0~99
        Counter3++;
        Counter3%=100;        //計數值變化范圍限制在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;
        }
}

void UART_Routine() interrupt 4    //串口中斷
{         

if(RI==1)   //允許單片機接收數據
{
        Data=SBUF;                   //讀取數據
        UART_SendByte(SBUF);  //將接收到的數據發回串口
        RI=0;  //接收標志位清0 軟件復位
}
}
回復

使用道具 舉報

9#
ID:844772 發表于 2023-8-24 10:43 | 只看該作者

UART_SendByte(SBUF);  //將接收到的數據發回串口
的后邊加一句:
Data-=48;
回復

使用道具 舉報

11#
ID:1071654 發表于 2023-8-24 16:53 | 只看該作者
glinfei 發表于 2023-8-24 10:43

UART_SendByte(SBUF);  //將接收到的數據發回串口
的后邊加一句:

按照您的指點在:UART_SendByte(SBUF); 后面增加了Data-=48;
驗證失敗,串口能收到數據,但所有指令均不識別,小車無任何動作
回復

使用道具 舉報

12#
ID:1071654 發表于 2023-8-24 16:57 | 只看該作者
ydatou 發表于 2023-8-24 12:01
只需要把IR_Tracking()函數中的“while(1)”這行注釋就可以了。

你代碼還有些問題。

把IR_Tracking()函數中的“while(1)”這行注釋就可以了。
//如上信息經過驗證,藍牙控制和紅外循跡指令均能識別。謝謝您

你代碼還有些問題。
Data這個全局變量表示最后收到的數據,還需要增加一個全局變量表示這數據是否已經處理。
//這部分代碼驗證中,感謝您的指導
回復

使用道具 舉報

13#
ID:1071654 發表于 2023-8-29 16:45 | 只看該作者
ydatou 發表于 2023-8-24 12:01
只需要把IR_Tracking()函數中的“while(1)”這行注釋就可以了。

你代碼還有些問題。

此部分代碼已驗證,可行。
回復

使用道具 舉報

14#
ID:1071654 發表于 2023-8-29 16:47 | 只看該作者
有一個小小的疑問,在主程序中定義了:
unsigned char Compare,Compare1,Compare2,Compare3;
unsigned char Counter,Counter1,Counter2,Counter3;
如果要把IR_Tracking()模塊化,那么是否也需要在IR_Tracking()里面再次定義?有點不太明白
回復

使用道具 舉報

15#
ID:1073939 發表于 2023-8-30 08:36 | 只看該作者
要在多個文件使用同一變量做法:
只在一個文件正常定義變量,其它文件變量定義加“extern”修飾,“extern”表示該變量定義在其它文件中。

其它方法,只在一個文件正常定義變量,其它文件不直接操作該變量,依賴函數操作。

回復

使用道具 舉報

16#
ID:1071654 發表于 2023-9-1 10:44 | 只看該作者
ydatou 發表于 2023-8-30 08:36
要在多個文件使用同一變量做法:
只在一個文件正常定義變量,其它文件變量定義加“extern”修飾,“extern ...

驗證可行,感謝哦!
回復

使用道具 舉報

17#
ID:517951 發表于 2023-9-5 07:48 | 只看該作者
建議把中斷里的函數拿出來, 放到main()中來執行.
中斷函數只需要做檢測外部事件, 根據外部事件設標志位,
main()
{
  while(1)
  {
   if(標志位1) function1();
  }
}
中根據外部事件標志位來執行相應的執行功能.
回復

使用道具 舉報

18#
ID:1071654 發表于 2023-9-5 09:28 | 只看該作者
rayin 發表于 2023-9-5 07:48
建議把中斷里的函數拿出來, 放到main()中來執行.
中斷函數只需要做檢測外部事件, 根據外部事件設標志位,
...

謝謝您的指點,當前按在您的方式來做,驗證功能可行
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品日韩一区二区 | 成人做爰9片免费看网站 | 久久99久久99 | 黑人巨大精品欧美一区二区免费 | 精品视频一区二区三区在线观看 | 色婷婷综合久久久中字幕精品久久 | 婷婷一级片 | 午夜视频一区二区 | 影音先锋中文在线 | 日本二区 | 99精品欧美一区二区三区 | 新av在线 | 日韩精品一区二区三区 | 日韩精品区 | 国产婷婷在线视频 | 精品免费国产一区二区三区 | 青青操91 | 在线观看日本高清二区 | 九九热视频这里只有精品 | 毛片入口 | 日韩欧美中文字幕在线视频 | 奇米影视首页 | 精品国产1区2区3区 一区二区手机在线 | 午夜免费在线电影 | 成人国产在线视频 | 日本免费小视频 | 狠狠久 | 国产无套一区二区三区久久 | 成人国产在线视频 | 亚洲男人网 | 韩日精品在线观看 | 久久久久久综合 | 91色视频在线| 国产精品久久久久国产a级 欧美日韩国产免费 | 久久精品视频在线观看 | 午夜精品久久久久久 | 久久免费国产视频 | 久久天天躁狠狠躁夜夜躁2014 | 亚洲a毛片 | 亚洲a在线视频 | 欧美一级片a |