- 先列出 function calls
- void delay_1ms(int k): 利用空迴圈, 跑110*k次
- void anti_cck(): 將4顆7段顯示器 逆時針轉3圈
- void pili_led(): 8顆LED左右跑3次。
- void pulse_BZ(int count, int TH, int TL): Buzzer的震動
- void mode0()
- void main(): 主程式, press==0, press==1, press==2
- x==1 沒做事, 顯示00
- sw==0 有按下 sw按鈕, 就把x=0, TR0 TR1都打開, 會count++ & 顯示
- sw2==0 有按下 sw2按鈕, press_add++, 等一下, 直到sw2放開, 開, 等一下
- press_add==0 一開始, 沒做事
- press_add==1
- press_add==2: TR0=1要顯示bcd[1],bcd[0], TR1=0 不會count++,
- press_add==3: 變回 press_add=0不做事, TR1=1要顥示 bcd[1], bcd[0]
- T0_int(void) interrupt 1: 5000us=5ms, 會去更新P0及P2的值, 讓 bcd[1] 及 bcd[0] 的值一直去顯示
- T1_int(void interrupt 3: 50000us=50ms, 會在 50ms*20=1sec去更新counter 並更新 bcd[1] bcd[0] 這兩位數, 即 00...99去(每秒)累增
- 開始逐行分析 (Keil C51 is based on C90)
- Keil C51 為 8051多了 bit, sbit, sfr, sfr16 (後3個是CPU特別register)
- C 語言:Keil C51 和標準 C 語言的差異
- AT89X52.h
- atmel/at89x52.h
- at89s52.h
- at89c52.h
- 許多不同型號的單晶片機
- P1table[] 應該是 pili燈要用的順序
- P0table[] 是一些字, P0table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- 1111 1001, 1010 0100, 1011 0000, 1001 1001, 1001 0010, 1000 0010, 1111 1000, 1000 0000, 1001 0000
- 合理猜測, 是7段顯示器要顯示0...9的數字
- 原來 0是發亮, 那了解了。
- 但是, pili_led()裡面, 是寫 P1=~P1table;
- sbit buzzer = P3^7
- P0是用來決定7段顯示器, P2是用朲決定是哪一個7段顯示器
- P1是8顆LED, 當它是 LOW時便會發亮。所以才會 P1=~P1table[pili_ed_i], 把它正負倒過來
- TR0, TR1
- TMOD
- Timer工作模式0時,13位元計時/計數值最大為8192(2的13次方),因此,THx的值應為計時/計數值除以32的商,TLx的值則為計時/計數值除以32的餘數。若計時/計數值為5000時,即
- TL0 = # (8192-5000)×MOD×32
- TH0 = # (8192-5000)/32
- TL0 = (65536 - 9217) % 256; // 計數時間 : 9217 * 1.085us = 0.01s
- 比如12MHZ来说吧,机器周期是1us,就是说每1us产生一次计数,就拿50ms来说,这是你想要的计时,意思是,对机器周期进行50000计数就可以得到我想要的
- 50ms*20=1000ms=1sec
- TH0=(8192-5000)/32;
- 假設計時器0 每 5ms 中斷一次,因機械週期為1us 則 N=5ms/1us=5000
- 所以 TH0=(8192-5000)/32 ,TL0=(8192-5000%32)
- 接下來, 怎麼讓程式碼可以有更好的架構?
- 條件: 要尊重原本 8051 在程式開發的習慣, 不要做太大的修改, 以便原本熟悉的人能快速使用
- 8051的重點是利用 Interrupt 的方法來實作
- Q: delay_1ms(k) 可以等待 k ms 的作法, 是常用的習慣, 要保留
- 但是如果 Timer Interrupt 時, 原本 delay_1ms() 會被打斷, 則會不合理
- Q: 有沒有準確的 clock? (我們可以利用 Timer interrupt 來製作準確的 clock, 再提供給我們的程式使用
- Q: 有沒有 sleep? A: _sleep_( ms )
- Q: Timer TR0 等 5000 即 5ms, Timer TR1 等 50000 即 50ms 要保留。
- 關鍵就是 Timer TR0,TR1 要幫忙決定要做什麼事。也成為 call back function 的基礎, 用來改變 flag, 程式碼不能太複雜。
- main()迴圈 就照著 flag來做事
- int task=1;
- void main(){
- init_setting();
- while(1){
- if(task==1) task1_seg7_rotate3_cck();
- else if(task==2) task2_8LED_rotate3();
- else if(task==3) task3_buzzer_beep3();
- else if(task==4) task4_mode0();
- else if(task==5) task5_increase_counter();
- else if(task==6) task6_pause();
- else if(task==7) task7_reset();
- // if(.... && ... ) task = ???
- // else if(....&& ...
- }
- }
- 接下來使用 Timer TR0, TR1 來修改 flag (含 state切換, 數值切換, 越快越好)
- button1, button2
- if(button1==0){//按下第1個按鈕, 決定上數 (or下數)
- if(button2==0){//按下第2個按鈕, 要判斷 2短按 1短按, 表示 Pause 還是 Resume
- Q: 長按按鈕 (Reset Couner), , 是 button1 還是 button2? 我先假裝是 button1, 因為 button1 就與 counter++/counter--/counter=0 有關, 容易操作
- Timer TR0, TR1 可以用來查 button的值, 如果是(沒有按下去變成) 按下去, 就記錄按下的時間 (Pressed)
- 如果是 (剛剛按下去變成) 放開, 就要記錄放開的時間 (Released)
- button1 都是在放開(Released)的時候, 來切換動作, 判斷是長按 or 短按
2019年10月9日 星期三
關於 8051 C的程式碼
訂閱:
張貼留言 (Atom)
algorithm
#include <iostream> #include <string.h> using namespace std; int main(int argc, char** argv) { for(int j=2;j<=100;j++)//j...
-
本文旨在補充《 超圖解Arduino互動設計入門 》第18章「RFID無線識別裝置與問答遊戲製作」單元,書本採用的RFID讀卡機模組是採用9600bps, TTL序列通訊介面,RFID的通訊頻率為125KHz。這種模組的接線和程式都很簡單,每當感測到RFID卡,讀卡機就把...
-
/* 多重按鈕開關 */ //==宣告區================================ #include // 定義8051暫存器之標頭檔,P2-17~19 #include "myio.h" // 自己寫的I/O程式庫 sbit PB...
沒有留言:
張貼留言