?? 單片機多任務的簡單實踐 .txt
字號:
單片機多任務的簡單實踐
作者:鄖縣公安局 梅松 442500 于2007-10-15上傳
--------------------------------------------------------------------------------
多任務和中斷聯系緊密,這里我們以mcs-51單片機作為實驗對象來實現簡單的多任務,這里舉個例子,中斷采用時鐘中斷任務數量為2,雖然次例子任務數量較少,但以此思路進行擴展不難實現更多任務。
微型計算機系統的運行可以簡單理解為cpu經過初始化后便成為了一個循環系統。驅動12864LCD和A/D轉換都是msc-51單片機比較常見的任務,這里便是將這兩個任務結合起來:把A/D轉換得到的數字信號在12864LCD以波形的方式顯示出來。為了實現這兩個任務需要設置變量來表示每個任務的工作狀態,這里選擇一個8位變量的低2位來表示每個任務是否在運行中。地址為23的變量AD_OPT就是這個8位變量,它得第7位表示主循環程序是否將采集到得數據取走(數據1為是0為否)第8位表示采集到得數據是否可用(1為是0為否)。由于主循環占用cpu資源較多,所以采集采用中斷方式。初始化時為了使采集得以進行先置第7位為1。具體程序代碼見下:
;* 控制器:KS0107 *
;* LCD型號:TS12864A-2或兼容型號 *
;* MCU:AT89S5* ,晶體頻率:11.0592MHz *
;* 取模方式:縱向字節倒序 *
;* CS1和CS2為高電平有效 *
;***************硬件端口定義***********
RS EQU P2.0 ;即DI;12864液晶信號
RW EQU P2.1 ;12864液晶信號
E EQU P2.2 ;12864液晶信號
CS1 EQU P2.3 ;12864液晶信號
CS2 EQU P2.4 ;12864液晶信號
RST EQU P2.5 ;12864液晶信號
LVCC EQU P2.6 ;12864背景燈地址
AD_CLK EQU P1.0 ;AD0832時鐘
AD_DI EQU P1.1 ;AD0832轉換數據
AD_CS EQU P3.4 ;AD0832片選
COM EQU 20H ;12864指令數據寄存器
DAT EQU 21H ;12864顯示數據寄存器
x equ 22h ;屏x直
AD_OPT EQU 23H ;AD采集數據狀態
;#0<-①0<-②0<-③0<-④ 0<-⑤0<-⑥0<-⑦0<-⑧B位
;⑦主程序已經取走數據1為是0為否
;⑧數據是否可用? 1為是0為否
AD_DAT EQU 24H ;AD采集到數據
;**********************************初始入口地址
ORG 0000H
LJMP MAIN
ORG 0003H ;外部中斷0
RETI
ORG 000BH ;定時器/計數器0溢出
LJMP TIMER
ORG 0013H ;外部中斷1
RETI
ORG 001BH ;定時器/計數器1溢出
RETI
ORG 0023H ;串行囗中斷
RETI
ORG 0030H
;*********************************時間中斷
TIMER:
PUSH ACC
PUSH PSW
MOV ACC,R1
PUSH ACC
LCALL AD_CONV
POP ACC
MOV R1,ACC
POP PSW
POP ACC
RETI
;---------------------------------------------------------
AD_CONV: ;ADC0832初始化 INT0
MOV A,AD_OPT
ANL A,#00000010B
JZ AD_RET ;A為0說明主程序尚未去走數據則直接返回
MOV A,#00H ;先清0
MOV P0,#0FFH
SETB AD_CS ;一個轉換周期開始
CLR AD_CLK
CLR AD_CS ;CS置0,片選有效
SETB AD_DI ;DI置1,起始位
SETB AD_CLK ;第一個脈沖
CLR AD_DI ;在負跳變之前加一個DI反轉操作
CLR AD_CLK
SETB AD_DI ;DI置1,設為單通道
SETB AD_CLK ;第二個脈沖
CLR AD_DI ;***
CLR AD_CLK ;
CLR AD_DI ;DI置0,選擇通道0
SETB AD_CLK ;第三個脈沖
SETB AD_DI ;***
CLR AD_CLK
NOP
SETB AD_CLK ; 第四個脈沖
MOV R1,#08H ;計數器初值,讀取8位數據,
AD_READ: CLR AD_CLK ;下降沿
MOV C,AD_DI ;讀取DO端數據
RLC A ;C移入A,高位在前
SETB AD_CLK ;下一個脈沖
DJNZ R1,AD_READ ;沒讀完繼續
SETB AD_CS
MOV AD_DAT,A ;轉換結果發給AD_DAT
;以下設置標志位
ORL AD_OPT,#00000001B ;置數據可用位為1
ANL AD_OPT,#11111101B ;置主取位為 0
AD_RET:
RET
;*********************************主程序入口地址
MAIN:
MOV SP,#60H
MOV TMOD,#01H
MOV TH0,#3CH
MOV TL0,#0A0H
SETB EA ;開總中斷允許
SETB ET0 ;開定時/計數器0允許
SETB TR0 ;定時/計數器0開始運行
ORL AD_OPT,#00000010B ;置主取位為1
CLR RST
NOP
NOP
SETB RST
CLR LVCC ;打開背景燈
LCALL LCD_INIT
LCALL CLEAR_ALL ;清整個屏幕
;**********************************************以上是軟件初始化
HEARE:
MOV R0,#000H
main1: MOV x,R0
LCALL CHECK_USE
mov a,x
anl a,#01000000B
jnz main_r
LCALL LEFT
jmp main2
main_r: LCALL RIGHT
main2: ORL AD_OPT,#00000010B ;置主取位為1
ANL AD_OPT,#11111110B ;置數據可用位為 0
INC R0
CJNE R0, #127,main1
LJMP HEARE
;********************************
LCD_INIT:
MOV COM,#3FH;顯示開
LCALL LEFT_COMM ;左半屏寫指令子程序
LCALL RIGHT_COMM ;右半屏寫指令子程序
;---------------------------------------------------------
MOV COM,#0C0H;第一行
LCALL LEFT_COMM ;左半屏寫指令子程序
LCALL RIGHT_COMM ;右半屏寫指令子程序
;---------------------------------------------------------- MOV COM,#0B8H;第一頁
LCALL LEFT_COMM ;左半屏寫指令子程序
LCALL RIGHT_COMM ;右半屏寫指令子程序
;----------------------------------------------------------
MOV COM,#40H;第一列
LCALL LEFT_COMM ;左半屏寫指令子程序
LCALL RIGHT_COMM ;右半屏寫指令子程序
ret
;****************************************** ****以下是子程序
CHECK_USE:;判斷數據是否可用不可用在子程序中循環
PUSH ACC
C_U_TM: MOV A,AD_OPT
ANL A,#00000001B
JZ C_U_TM ;A為0說明數據可用位為0,ad數據不可用,循環測試直到數據可用
POP ACC
RET
CHECK_BUSY: MOV P0,#0FFH ;檢測12864液晶屏狀態 空閑返回,否則在此子程序中循環
SETB E
MOV A,P0
CLR E
JB ACC.7,CHECK_BUSY
RET
SEND_COMMD: CLR RS ;發送命令到p0口
SETB RW
LCALL CHECK_BUSY
CLR RW
MOV P0,COM
SETB E
NOP
CLR E
RET
SEND_DATE: CLR RS ;發送數據到p0口
SETB RW
LCALL CHECK_BUSY
SETB RS
CLR RW
MOV P0,DAT
SETB E
NOP
CLR E
RET
LEFT_COMM: SETB CS1 ;左半屏寫指令子程序
LCALL SEND_COMMD
CLR CS1
RET
LEFT_DATE: SETB CS1 ;左半屏寫數據子程序
LCALL SEND_DATE
CLR CS1
RET
RIGHT_COMM: SETB CS2 ;右半屏寫指令子程序
LCALL SEND_COMMD
CLR CS2
RET
RIGHT_DATE: SETB CS2 ;右半屏寫數據子程序
LCALL SEND_DATE
CLR CS2
RET
LEFT:
MOV A,R0 ;主循環用到了r0
PUSH ACC
MOV R0,#0B8H
L_CLR_QUEUE: MOV COM,R0
LCALL LEFT_COMM
mov a,x
anl a,#00111111B
add a,#01000000B
MOV COM,A
LCALL LEFT_COMM
MOV DAT,#00H
LCALL LEFT_DATE
INC R0
CJNE R0, #0C0H,L_CLR_QUEUE
MOV A,AD_DAT
PUSH ACC
ANL A,#11100000B
SWAP A
RR A
MOV R0,#008H
XCH A,R0
SETB C
SUBB A,R0
MOV R0,#0B8H
ADD A,R0
MOV COM,A
LCALL LEFT_COMM ;左半屏寫指令子程序
mov a,x
anl a,#00111111B
add a,#01000000B
MOV COM,A
LCALL LEFT_COMM ;左半屏寫指令子程序
POP ACC
ANL A,#00011100b
RR A
RR A
DEC A
MOV R0,A
MOV A,#040H
L_LOOP: RR A
DJNZ R0,L_LOOP
MOV DAT,A
LCALL LEFT_DATE ;左半屏寫數據子程序
POP ACC
MOV R0,A
RET
RIGHT: MOV A,R0
PUSH ACC
MOV R0,#0B8H
R_CLR_QUEUE: MOV COM,R0
LCALL RIGHT_COMM
mov a,x
anl a,#00111111B
add a,#01000000B
MOV COM,A
LCALL RIGHT_COMM
MOV DAT,#00H
LCALL RIGHT_DATE
INC R0
CJNE R0, #0C0H,R_CLR_QUEUE
MOV A,AD_DAT
PUSH ACC
ANL A,#11100000B
SWAP A
RR A
MOV R0,#008H
XCH A,R0
SETB C
SUBB A,R0
MOV R0,#0B8H
ADD A,R0
MOV COM,A
LCALL RIGHT_COMM ;左半屏寫指令子程序
mov a,x
anl a,#00111111B
add a,#01000000B
MOV COM,A
LCALL RIGHT_COMM ;左半屏寫指令子程序
POP ACC
ANL A,#00011100b
RR A
RR A
DEC A
MOV R0,A
MOV A,#040H
R_LOOP: RR A
DJNZ R0,R_LOOP
MOV DAT,A
LCALL RIGHT_DATE ;左半屏寫數據子程序
POP ACC
MOV R0,A
RET
CLEAR_ALL: MOV R1,#0B8H ;清顯示屏
CLEAR_TMP1: MOV COM,R1
LCALL LEFT_COMM
LCALL RIGHT_COMM
MOV COM,#40H
LCALL LEFT_COMM
LCALL RIGHT_COMM
MOV R0, #64
CLEAR_TMP2: MOV DAT,#00H
LCALL LEFT_DATE
LCALL RIGHT_DATE
DJNZ R0,CLEAR_TMP2
INC R1
CJNE R1, #0C0H,CLEAR_TMP1
RET
END
由于程序未經過優化,所以顯得有些冗余,您若有比較好的想法意見建議請和我聯系:e-mail:332779423@qq.com
2007年9月29日
--------------------------------------------------------------------------------
歡迎訪問AoGo匯編小站:http://www.aogosoft.com 下一篇>>>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -