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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 5247|回復: 8
收起左側

RTX51tiny復雜應用---時鐘、溫度顯示、按鍵解析 源程序

  [復制鏈接]
ID:79874 發表于 2020-2-2 19:23 | 顯示全部樓層 |閱讀模式
一、設計需求


在清翔51單片機開發板上,用帶RTOS的方式實現下面的功能:


1. 板上有8個段碼LED,左邊的4個做一個計時器,顯示“MSS.Z”,其中M為分鐘,SS為秒,Z為n×0.1秒;右側的4個,其中3個顯示從18B20采集的實時溫度,最后1個顯示鍵盤的按鍵值,按鍵延時顯示按鍵0.3秒(也就是松開按鍵之后還繼續顯示0.3秒);


2. 在板上的LCD1602上,構建一個HH:MM:SS 時分秒的鐘表,同時將DS18B20的轉換結果也顯示在這里。


二、題目分析


面對一個復雜的題目,我們需要逐步實現需要的功能。先實現一個獨立的功能,然后再增加功能,慢慢就能達到完整的要求。在實現獨立功能的時候要考慮代碼的可綜合性,要盡量構建易于被調用的函數,在后期將會大大方面我們的綜合優化。


編寫代碼的時候,盡量養成良好的習慣。對于一個龐大的工程,其必定可以分割為很多小模塊。本題中用到了數碼管、LCD1602、DS18B20、矩陣鍵盤這些外設,我們可以單獨構建這些模塊的驅動函數,后面再加以綜合。


在創建好RTOS工程之后,在工程文件夾下再創建一個hardware文件夾,然后在這個文件夾里為每個外設都創建一個文件夾,如下圖所示。






每一個外設都對應一個C文件和H文件,這兩個文件放置在各自的文件夾中。這里還需要注意在keil中需要將這幾個文件夾添加到編譯路徑中,要不然軟件找不到H文件。在option中的incliude path處添加需要的路徑。


做完這些準備工作后,我們就可以來分模塊來構建我們的代碼了。


三、模塊分析


3.1 數碼管


3.1.1 數碼管顯示函數


在使用的51開發板上,一共有8個數碼管。這里我們可以編寫一個函數,讓其每一位可以單獨顯示任意數字。入口參數即為每一位要顯示的數字,后面需要用到顯示的地方,只需要傳入對應的變量即可。比如構造如下的函數:


void play_SMG(unsigned char led7,led6,led5,led4,led3,led2,led1,led0);


在實際使用的時候,比如想讓數碼管顯示1234567,就只需這樣寫:play_SMG(1,2,3,4,5,6,7)。一般我們都是要求數碼管動態顯示的,這時我們把對應的變量傳入相應的位置即可。


函數內部的詳細代碼比較簡單參見附錄。


3.1.2 數碼管閃爍問題


使用RTOS的時候,由于程序是輪循執行的。假如在一個任務中讓數碼管顯示,就存在兩個問題。


輪循時間間隔太短,數碼管來不及全部顯示。
任務數量太多,下一次顯示間隔太長。
這里要搞清楚輪循的時間怎么計算。輪循時每個任務執行的時間是固定的,這個時間具體可以通過INT_CLOCK和TIMESHARING相乘得到。默認的INT_CLOCK = 10000,TIMESHARING = 5。也就是每個任務執行時間為50ms。


不光是數碼管,每個任務在執行的時候都存在這個問題。在調試數碼管的時候,會發現閃爍嚴重,就是上面兩個因素的影響。相比之下,后者影響更大。假如有4個任務,按照默認的時間片設定,每次顯示之后就要等待至少150ms。這個間隔內數碼管是不顯示的,就會看到數碼管間歇性亮,或者很晃眼。


這時候可以通過更改時間片來獲得比較好的顯示效果。


3.2 時鐘


3.2.1 產生時間基準


我們可以通過讓數碼管顯示一個時鐘來驗證我們的函數正確性,同時這也是題目要求的一部分。


對于時鐘的構建,可以先設定一個最小的時間基準,比如100ms,每個100ms對應的變量自加一次。10個100ms之后即1s的時候,代表秒的變量自加一次。當秒個位加到9的時候,十位加一,當59秒的時候再過1秒,秒清零同時分的個位加一……,這個過程寫起來比較繁瑣,需要細心不要搞錯了。


這里的主要問題是怎么產生100ms的時間間隔。我們可以在一個任務中產生我們的時鐘。100ms的間隔用延時函數來產生。


關于RTOS的延時,系統中給了os_wait2( ),這個函數有兩個輸入參數,詳細可以看幫助文檔。這里需要注意一個tick代表多長時間,這個可以在Conf_tny.51文件中查看,通過INT_CLOCK的值來計算,默認值為10000,如果使用12M的晶振,那么這里就是10ms,也就是說如果我們寫了os_wait2( K_TMO,1),就是代表延時10ms。我們會發現這里最小的延時單位只能是10ms。可以更改INT_CLOCK的值來減小延時單位長度。這里我將INT_CLOCK的值改為了1000,那么一個延時單位就是1ms。需要注意,os_wait2( )中的參數類型是unsigned char,意味著我們最大只能寫255,如果需要更長的延時,可以通過for循環來構建。


3.2.2 時鐘顯示


定義用來表示時鐘的變量:uchar H1,H0,M1,M0,S1,S0,Z;


H、M、S分別為時分秒,Z為n×0.1秒。時鐘的產生比較簡單,就是需要的邏輯性比較強,詳細的代碼參見附錄。


然后如下編寫job0的代碼:


void job0 (void) _task_ 0

{

    os_create_task (1);

    while (1)

    {

          play_SMG(M0,S1,S0,Z,0,0,0,0);     

    }

}
可以看到前四個數碼管顯示了計時器的值,后四個數碼管一直顯示0。這說明我們的代碼是沒有問題的。對于時鐘的產生,這里采用了比較直觀的方式去產生,易于理解,但是寫起來需要注意代碼的邏輯性。我們也可以嘗試使用更簡潔的方式去構建。


通過這個過程我們也可以發現代碼的綜合其實并不難,就是一步一步添加功能的過程。


3.3 鍵盤顯示


3.3.1 矩陣鍵盤掃描


矩陣鍵盤掃描的函數有很多,它的原理網上也講的很多,不再贅述。


很多時候我們要做的并不是自己如何去寫一個器件的驅動程序,是如何把別人拿過來用。看懂別人的代碼,可以改善并融合到自己的程序中是最好的。


假如現在手頭有一個鍵盤掃描的代碼,當檢測到某個按鍵按下的時候會返回一個值,不同的按鍵按下有不同的返回值。該怎么將其加入到我們的代碼中呢?


這里可以創建一個任務用來進行按鍵檢測,并創建一個變量key用來表示按鍵值。通過不同的按鍵返回值來給key進行賦值。截取部分代碼如下:


void keys (void) _task_ 3

{

    while (1)

    {

        switch( KeyScan() )

        {

            //第一行鍵值碼

            case 0xee: key = 0;       break;

            case 0xde: key = 1;       break;

            case 0xbe: key = 2;       break;

            case 0x7e: key = 3;       break;

            ……

        }

    }

}
在任務三中key的值將根據按鍵的值改變。接下來我們只需要將按鍵的值送給數碼管顯示即可。play_SMG(M0,S1,S0,Z,0,0,0,key),將key放在數碼管顯示函數的最后一位。這樣我們又完成了一個功能的添加,也沒有改變程序原本運行的狀態。


3.3.2 清除按鍵顯示


在題目中要求按鍵延時顯示按鍵0.3秒(也就是松開按鍵之后還繼續顯示0.3秒);也就是在手松開0.3秒之后要清除顯示。


這里可以設置一個標志位flag,當按鍵按下的時候讓flag置1,并且延時300ms后將flag清0。這樣我們就可以通過flag的狀態判斷按鍵有沒有按下,并且flag是滯后于手松開300ms刷新的。具體的代碼如下:


unsigned char KeyScan() //帶返回值的子函數

{

   unsigned char i;

      unsigned char cord_l,cord_h;//聲明列線和行線的值的儲存變量

      P3 = 0x0f;//0000 1111

      if( (P3 & 0x0f) != 0x0f)//判斷是否有按鍵按下

      {

        os_wait2(K_TMO,5);//軟件消抖

             if( (P3 & 0x0f) != 0x0f)//判斷是否有按鍵按下

             {

                      cord_h = P3 & 0x0f;// 儲存行線值

                      P3 = cord_l | 0xf0;

                      cord_l = P3 & 0xf0;// 儲存列線值

            flag = 1;

            return (cord_l + cord_h);//返回鍵值碼                    

             }   

      }

    if(flag)

    {

        for(i = 0; i < 3; i++)

        {


^^^^^
keil工程下載地址:
RTOS復雜應用.zip (100.71 KB, 下載次數: 114)


評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復

使用道具 舉報

ID:65956 發表于 2020-2-4 21:13 | 顯示全部樓層
我也曾在幾個項目中用過,但沒有這么復雜,就是要搞清邏輯就可以了,把各個要執行函數分配到任務中,注意任務時間的區別與錯開,這樣就不會沖突了

評分

參與人數 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

ID:92004 發表于 2020-4-1 13:35 | 顯示全部樓層
18b20中仍就用到了delay等待,沒有用到 os_wait

評分

參與人數 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

ID:902133 發表于 2021-5-23 00:06 | 顯示全部樓層
我的IIC傳感器效率較低,同時還要處理通訊需求,不指導可不可以用。
回復

使用道具 舉報

ID:28992 發表于 2021-5-23 01:57 | 顯示全部樓層
thank you sir!
回復

使用道具 舉報

ID:929300 發表于 2021-5-29 22:55 | 顯示全部樓層
18b20延時怎么保證數碼管不閃
回復

使用道具 舉報

ID:527324 發表于 2021-8-3 16:17 | 顯示全部樓層
多任務讀寫25芯片咋弄啊
回復

使用道具 舉報

ID:140644 發表于 2022-10-12 11:03 | 顯示全部樓層
先下了看看,等一下試試能不能編譯
回復

使用道具 舉報

ID:1134130 發表于 2024-10-20 12:12 | 顯示全部樓層
wizarder 發表于 2020-4-1 13:35
18b20中仍就用到了delay等待,沒有用到 os_wait

因該可以直接用os_wait替換
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 碰碰视频 | 夜夜爽99久久国产综合精品女不卡 | 精品免费av | 91在线看片 | 黄网站涩免费蜜桃网站 | 国产日韩欧美一区二区 | 色综合99 | 日韩国产专区 | www.中文字幕.com | 色呦呦在线 | 亚州精品天堂中文字幕 | 国产色99| 91精品国产综合久久久久久漫画 | 国产三区四区 | 国产精品一区二区久久 | 午夜精品导航 | 成人免费黄色 | 91精品久久久久久久久久 | 麻豆久久久9性大片 | 91av小视频| 中文字幕亚洲视频 | 久久久久久av| 理伦毛片 | 精品中文在线 | 一级毛片视频 | 国产免费av网 | av中文字幕网| 午夜欧美一区二区三区在线播放 | 成人在线免费视频 | 精品一区久久 | 性色综合| 紧缚调教一区二区三区视频 | 在线观看中文字幕 | 午夜私人影院在线观看 | 最新中文字幕在线播放 | 国产亚洲高清视频 | av一级在线观看 | www.一区二区三区 | 国产九九精品视频 | 中文字幕免费中文 | 久久精品免费一区二区三 |