單片機簡易紅綠燈編程
❶ 交通燈 C語言 單片機。中斷函數問題
參考《51單片機C語言創新教程》溫子祺等著。
源碼轉自:《51單片機C語言創新教程》。
/*實驗名稱:交通燈實驗
*描述:交通燈實驗要求紅燈亮15秒,綠燈亮10秒,黃燈亮5秒,
當紅燈切換為綠燈或者綠燈切換為紅燈,
要實現燈閃爍。紅燈、綠燈、黃燈的點亮持續時間可以通過串口來修改,
並在下一個循環中更新數值。
*作者:溫子祺
*修改日期:2010/5/4
*說明:代碼注釋與講解詳見《51單片機C語言創新教程》溫子祺等著,北京航空航天大學出版社
*/
#include"stc.h"
typedefunsignedcharUINT8;
typedefunsignedint UINT16;
typedefunsignedlongUINT32;
typedefcharINT8;
typedefintINT16;
typedeflongINT32;
#defineTIMER0_INITIAL_VALUE5000
#defineHIGH1
#defineLOW0
#defineON1
#defineOFF0
#defineSEG_PORTP0
#defineLS164_DATA(x){if((x))P0_4=1;elseP0_4=0;}
#defineLS164_CLK(x){if((x))P0_5=1;elseP0_5=0;}
#defineNORTH_R_LIGHT(x){if((x))P2_0=0;elseP2_0=1;}
#defineNORTH_Y_LIGHT(x){if((x))P2_1=0;elseP2_1=1;}
#defineNORTH_G_LIGHT(x){if((x))P2_2=0;elseP2_2=1;}
#defineSOUTH_R_LIGHT(x){if((x))P2_3=0;elseP2_3=1;}
#defineSOUTH_Y_LIGHT(x){if((x))P2_4=0;elseP2_4=1;}
#defineSOUTH_G_LIGHT(x){if((x))P2_5=0;elseP2_5=1;}
#defineTRAFFIC_STATUS_10
#defineTRAFFIC_STATUS_21
#defineTRAFFIC_STATUS_32
#defineUART_MARKER0xEE
UINT8Timer0IRQEvent=0;
UINT8Time1SecEvent=0;
UINT8Time500MsEvent=0;
UINT8TimeCount=0;
UINT8SegCurPosition=0;
UINT8LightOrgCount[4]={15,5,15,5};
UINT8LightCurCount[4]={15,5,15,5};
UINT8TrafficLightStatus=0;
codeUINT8SegCode[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
UINT8SegBuf[4]={0};
codeUINT8SegPosition[4]={0x07,0x0b,0x0d,0x0e};
typedefstruct_LIGHT_VAL
{
UINT8Head;
UINT8val[4];
}LIGHT_VAL;
typedefunion_LIGHT_VAL_EX
{
LIGHT_VALlv;
UINT8p[5];
}LIGHT_VAL_EX;
voidLS164Send(UINT8byte)
{
UINT8j;
for(j=0;j<=7;j++)
{
if(byte&(1<<(7-j)))
{
LS164_DATA(HIGH);
}
else
{
LS164_DATA(LOW);
}
LS164_CLK(LOW);
LS164_CLK(HIGH);
}
}
voidRefreshDisplayBuf(UINT8s1) //刷新顯示緩存
{
SegBuf[0]=s1%10;
SegBuf[1]=s1/10;
SegBuf[2]=s1%10;
SegBuf[3]=s1/10;
}
voidSegDisplay(void)
{
UINT8t;
t=SegCode[SegBuf[SegCurPosition]];
SEG_PORT|=0x0f;
LS164Send(t);
SEG_PORT=(SEG_PORT|0x0f)&SegPosition[SegCurPosition];
if(++SegCurPosition>=4)
{
SegCurPosition=0;
}
}
voidTimerInit(void)
{
TH1=0;
TL1=0;
TH0=(65536-TIMER0_INITIAL_VALUE)/256;
TL0=(65536-TIMER0_INITIAL_VALUE)%256;//定時1MS
TMOD=0x51; /*01010001T1計數,T0定時*/
}
voidTimer0Start(void)
{
TR0=1; //啟動計時器1
ET0=1;
}
voidTimer0Stop(void)
{
TR0=0; //啟動計時器1
ET0=0;
}
voidPortInit(void)
{
P0=P1=P2=P3=0xFF;
}
voidUartInit(void)
{
SCON=0x40;
T2CON=0x34;
RCAP2L=0xD9;
RCAP2H=0xFF;
REN=1;
ES=1;
}
voidUartSendByte(UINT8byte)
{
SBUF=byte;
while(TI==0);
TI=0;
}
voidUartPrintfString(INT8*str)
{
while(str&&*str)
{
UartSendByte(*str++);
}
}
voidmain(void)
{
UINT8i=0;
PortInit();
TimerInit();
Timer0Start();
UartInit();
RefreshDisplayBuf(LightCurCount[0]);
EA=1;
NORTH_R_LIGHT(ON);
SOUTH_G_LIGHT(ON);
while(1)
{
if(Timer0IRQEvent)
{
Timer0IRQEvent=0;
TimeCount++;
if(TimeCount>=200)
{
TimeCount=0;
if(LightCurCount[0])
{
TrafficLightStatus=0;
}
elseif(LightCurCount[1])
{
TrafficLightStatus=1;
}
elseif(LightCurCount[2])
{
TrafficLightStatus=2;
}
elseif(LightCurCount[3])
{
TrafficLightStatus=3;
}
else
{
for(i=0;i<4;i++)
{
LightCurCount[i]=LightOrgCount[i];
}
TrafficLightStatus=0;
}
switch(TrafficLightStatus)
{
case0:
{
NORTH_R_LIGHT(ON);
SOUTH_R_LIGHT(OFF);
NORTH_G_LIGHT(OFF);
SOUTH_G_LIGHT(ON);
NORTH_Y_LIGHT(OFF);
SOUTH_Y_LIGHT(OFF);
}
break;
case1:
{
if(LightCurCount[1]%2)
{
NORTH_R_LIGHT(ON);
SOUTH_G_LIGHT(ON);
}
else
{
NORTH_R_LIGHT(OFF);
SOUTH_G_LIGHT(OFF);
}
NORTH_Y_LIGHT(ON);
SOUTH_Y_LIGHT(ON);
}
break;
case2:
{
NORTH_R_LIGHT(OFF);
SOUTH_R_LIGHT(ON);
NORTH_G_LIGHT(ON);
SOUTH_G_LIGHT(OFF);
NORTH_Y_LIGHT(OFF);
SOUTH_Y_LIGHT(OFF);
}
break;
case3:
{
if(LightCurCount[3]%2)
{
NORTH_G_LIGHT(ON);
SOUTH_R_LIGHT(ON);
}
else
{
NORTH_G_LIGHT(OFF);
SOUTH_R_LIGHT(OFF);
}
NORTH_Y_LIGHT(ON);
SOUTH_Y_LIGHT(ON);
}
break;
default:break;
}
RefreshDisplayBuf(LightCurCount[TrafficLightStatus]);
LightCurCount[TrafficLightStatus]--;
}
SegDisplay();
}
}
}
voidUartIRQ(void)interrupt4
{
staticUINT8cnt=0;
staticLIGHT_VAL_EXLightValEx;
if(RI)
{
RI=0;
LightValEx.p[cnt++]=SBUF;
if(LightValEx.lv.Head==UART_MARKER)
{
if(cnt>=5)
{
for(cnt=1;cnt<5;cnt++)
{
LightOrgCount[cnt-1]=LightValEx.lv.val[cnt];
LightCurCount[cnt-1]=LightValEx.lv.val[cnt];
}
cnt=0;
UartPrintfString("設置交通燈完成 ");
}
}
else
{
cnt=0;
}
}
}
voidTimer0IRQ(void)interrupt1
{
ET0 =0;
TH0=(65536-TIMER0_INITIAL_VALUE)/256;
TL0=(65536-TIMER0_INITIAL_VALUE)%256;//定時1MS
Timer0IRQEvent=1;
ET0 =1;
}
=====================================================================
坐等拿分!
❷ 求大神解答,用51單片機匯編語言實現一個紅綠燈的程序,不是一個路口的,大概注釋下就好
;------------------------------------
;程序實現功能
;西南北路口直行與轉彎交替通行,數碼管顯示直行通行倒計時,紅綠黃燈顯示包括人行道在內的道路交通狀態。
;某一方向道路擁擠時,可以人工控制調節東西南北方向通行時間。
;緊急情況時,各路口交通燈顯示紅燈,數碼管保持數據不變。
;工作寄存器及存儲單元分配
;1.工作寄存器
;R2設置為定時器定時中斷次數,R6、R7用於延時程序中的寄存器
;2.片內存儲單元
;30H、31H作為兩組數碼管顯示數據存儲單元;32H、33H作為交通燈初始狀態存儲單元;40H、41H作為交通燈顯示數據存儲單元
;3.標志位
;00H:南北通行標志位 ; 01H:東西通行標志位;02H:緊急事件標志位
;-----------------------------------
SNF EQU 00H ;;;南北通行標志位
EWF EQU 01H ;;;東西通行標志位
URF EQU 02H ;;;緊急事件標志位
ORG 0000H
LJMP MAIN ;;;上電轉主程序
ORG 000BH ;;;定時中斷入口
LJMP DSZD
ORG 0003H ;;;緊急中斷入口
LJMP URZD
ORG 0030H
MAIN: LCALL INIT ;;;調用初始化子程序
LOOP: LCALL DIS ;;;循環執行顯示子程序
AJMP LOOP
;///////////初始化程序
INIT: SETB SNF
SETB EWF
SETB URF
MOV R2,#20 ;;;定時器中斷20次為1s
MOV TMOD,#01H ;;;初始化定時器
MOV TL0,#0B0H
MOV TH0,#3CH
SETB EA ;;;開定時中斷與緊急中斷
SETB ET0
SETB TR0
SETB EX0
SETB IT0 ;;;設置中斷程式控制方式
MOV DPTR,#TAB ;;;數值首地址放入DPTR中
MOV 40H,#40 ;;;東南西北通行時間設置
MOV 41H,#40
MOV 30H,#40 ;;;通行時間初始化
MOV 31H,#60
MOV P0,#4CH ;;;初始化時南北通行並把交通燈狀態分別放在32H和33H中
MOV 32H,#4CH
MOV P2,#15H
MOV 33H,#15H
RET
;////////////顯示子程序
DIS: MOV P3,#0DFH ;;;選中南北方向的十位數碼管
MOV A,30H ;;;把顯示數據送人數碼管顯示
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV P1,A ;;;
LCALL D1MS
MOV P3,#0EFH ;;;選中南北方向的個位數碼管
MOV A,B ;;;送入數碼管顯示
MOVC A,@A+DPTR
MOV P1,A
LCALL D1MS
MOV P3,#7FH ;;;選中第東西方向的十位數碼管
MOV A,31H ;;;送入數碼管顯示
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV P1,A
LCALL D1MS
MOV P3,#0BFH ;;;選中第東西方向的個位數碼管
MOV A,B
MOVC A,@A+DPTR
MOV P1,A
LCALL D1MS
SETB P3.0
SETB P3.1
JNB P3.0,DIS_S ;;;查詢是否第一個按鍵按下
JNB P3.1,DIS_E ;;;查詢是否第二個按鍵按下
AJMP DIS_R ;;;沒有鍵按下則返回
DIS_S:LCALL D5MS ;;;按鍵去抖
JNB P3.0,DIS_SN
AJMP DIS_R
DIS_SN:MOV 40H,#50 ;;;對通行時間從新分配,南北通行時間加長
MOV 41H,#30
AJMP DIS_R
DIS_E:LCALL D5MS ;;;按鍵去抖
JNB P3.1,DIS_EW
AJMP DIS_R
DIS_EW:MOV 40H,#30 ;;;東西通行時間加長
MOV 41H,#50
DIS_R:RET
;///////定時中斷處理程序
DS_C: LJMP DS_R ;;;接力跳轉
DSZD: PUSH ACC ;;;保護現場
PUSH PSW
CLR TR0 ;;;關定時器及中斷標志位並重新賦值
CLR TF0
MOV TL0,#0B0H
MOV TH0,#3CH
DJNZ R2,DS_C ;;;判斷1m時間是否到達
MOV R2,#20 ;;;到達重新賦值
DEC 30H ;;;南北方向通行時間減一
MOV A,30H ;;;把減一後的時間送入顯示存儲單元
;;;;;;;南北通行到達最後4秒時黃燈閃爍
DS_10:CJNE A,#4,DS_11 ;;;如果通行時間剩餘4秒
JNB SNF,DS_11 ;;;判斷是否是南北通行
MOV P0,#8AH
MOV 32H, #8AH ;;;把交通燈狀態存入存儲單元(後面類似)
DS_11:CJNE A,#3,DS_12 ;;;不是剩餘3秒,返回
JNB SNF,DS_12 ;;;不是南北通行時間,返回
MOV P0,#88H
MOV 32H, #88H
DS_12:CJNE A,#2,DS_13
JNB SNF,DS_13
MOV P0,#8AH
MOV 32H, #8AH
DS_13:CJNE A,#1,DS_14
JNB SNF,DS_14
MOV P0,#88H
MOV 32H, #88H
;------------------------
DS_14:JNZ DS_NE ;;;通行時間沒有結束轉向改變東西方向的數碼管
CPL SNF ;;;如果通行時間結束則對標志位取反
JNB SNF,DS_1 ;;;判斷是否南北通行
MOV 30H,40H ;;;是,點亮相應的交通燈
MOV P0,#4CH
MOV 32H,#4CH ;;;存儲交通燈狀態
MOV P2,#15H
MOV 33H, #15H ;;;存儲交通燈狀態
DS_NE:DEC 31H ;;;東西方向通行時間減一
MOV A,31H ;;;把通行剩餘時間送入顯示存儲單元
;;;;;;;;東西方向通行時間剩餘4秒鍾黃燈閃爍(程序注釋與南北方向類似 略)
DS_20:CJNE A,#4,DS_21
JB EWF,DS_21
MOV P0,#51H
MOV 32H, #51H
DS_21:CJNE A,#3,DS_22
JB EWF,DS_22
MOV P0,#41H
MOV 32H, #41H
DS_22:CJNE A,#2,DS_23
JB EWF,DS_23
MOV P0,#51H
MOV 32H, #51H
DS_23:CJNE A,#1,DS_24
JB EWF,DS_24
MOV P0,#41H
MOV 32H, #41H
;-----------------------------
DS_24:JNZ DS_R ;;;東西方向時間沒有結束,返回
CPL EWF ;;;對通行狀態取反
JNB EWF,DS_2 ;;;東西方向通行時間到來,跳轉
MOV 31H,#80 ;;;東西方向通行結束,重新顯示時間
MOV P0,#89H ;;;點亮相應的交通燈
MOV 32H, #89H
MOV P2,#29H
MOV 33H, #29H
AJMP DS_R
DS_1: MOV 30H,#80 ;;;南北通行時間結束,重新對顯示存儲單元賦值
MOV P0,#89H ;;;執行轉彎狀態1
MOV 32H, #89H
MOV P2,#26H
MOV 33H, #26H
AJMP DS_NE
DS_2: MOV 31H,41H ;;;東西方向開始通行,賦值予顯示存儲單元
MOV P0,#61H ;;;點亮相應的交通燈
MOV 32H, #61H
MOV P2,#15H
MOV 33H, #15H
DS_R: SETB TR0
POP PSW ;;;恢復現場
POP ACC
RETI
;/////////////緊急中斷處理程序
URZD: PUSH ACC ;;;保護現場
PUSH PSW
CLR IE0 ;;;清除中斷標志位
CLR TR0 ;;;關定時器
CPL URF ;;;緊急事件標志位
JB URF,UR_CON ;;;緊急結束;跳轉
MOV P0,#49H ;;;各路口燈全顯示紅燈亮
MOV P2,#15H
AJMP UR_R
UR_CON:SETB TR0 ;;;恢復正常交通
MOV A,32H
MOV P0,A
MOV A,33H
MOV P2,A
UR_R: POP PSW ;;;恢復現場
POP ACC
RETI
;////////////查表指令0,1,2,3,4,5,6,7,8,9
TAB: DB 3FH, 06H, 5BH, 4FH, 66H, 6DH
DB 7DH, 07H, 7FH, 6FH
;//////////延時5ms與1ms
D5MS: MOV R7,#5
D1MS: MOV R7,#10
MOV R6,#50
L1: DJNZ R6,$
DJNZ R7,L1
RET
❸ 鍗曠墖鏈篊璇璦綰㈢豢鐏紼嬪簭錛岃佹眰錛氭暟鐮佺℃樉紺烘椂闂村掕℃椂銆16*16LED鐐歸樀鏄劇ず妯″潡鏄劇ず綰㈢豢榛勭伅銆
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
#define BLKN 2 //鍒楅攣瀛樺櫒鏁
sbit G = P1^7; //P1.7涓烘樉紺轟笡闄鍏佽告帶鍒朵俊鍙風鍙
sbit RCLK = P2^0; //P2.0涓鴻緭鍑洪攣瀛樺拹鑼勫櫒鏃墮挓淇″彿絝
sbit SCLR = P2^1; //P2.1涓虹Щ浣嶅瘎瀛樺櫒娓呪棆絝
void delay(uint); //寤舵椂鍑芥暟
uchar data display[32]; //鏄劇ず緙撳瓨
uchar code BMP[][32]={{16,0,16,0,37,248,36,64,120,64,8,64,16,64,32,64,124,64,0,64,0,64,12,64,112,64,3,252,0,0,0,0},
{16,0,19,240,32,16,41,240,120,16,19,252,32,64,122,72,1,80,0,224,25,80,102,76,0,64,1,192,0,0,0,0},
{4,64,4,64,63,248,4,64,127,252,1,0,31,240,17,16,31,240,17,16,31,240,8,32,16,16,32,8,0,0,0,0}}; //瀛楁ā琛'綰⑩樷欑豢鈥樷橀粍鈥
void main()
{
register uchar i,j;
SCON=0x00; //涓插彛宸ヤ綔妯″紡0錛氱Щ浣嶅瘎瀛樺櫒鏂瑰紡
TMOD=0x01; //瀹氭椂鍣═0宸ヤ綔鏂瑰紡1錛16浣嶆柟寮
P1=0x3f; //P1絝鍙e垵鍊礆細鍏佽告帴鏀躲侀攣瀛樸佹樉紺
TR0=1; //鍚鍔ㄥ畾鏃跺櫒T0
ET0=1; //鍏佽稿畾鏃跺櫒T0涓鏂
EA=1; //寮鍚鎬諱腑鏂錛
while(1)
{
delay(2000);
for(j=0;j<3;j++)
{
for(i=0;i<32;i++)
{
display[i]=~BMP[j][i];
if (i%2) delay(100);
}
delay(10000);
}
}
}
void delay(uint x)
{
register uchar i,j;
for (i=x;i>0;i--)
for (j=120;j>0;j--);
}
void leddisplay(void) interrupt 1 using 1
{
register uchar i, j=BLKN;
TH0 =(65536-100)/256; //琛¢儜瀵熻懼畾鏄劇ず灞忓埛鏂扮巼姣忕60甯
TL0 =(65536-100)%256;
i = P1; //璇誨彇褰撳墠鏄劇ず鐨勮屽彿
i = ++i & 0x0f; //琛屽彿鍔1錛屽睆钄介珮4浣
while(j)
{
j--;
SBUF = display[i*BLKN + j]; //閫佹樉紺烘暟鎹
while (!TI);
TI = 0;
} //瀹屾垚涓琛屾暟鎹鐨勫彂閫
G = 1; //娑堥殣錛堝叧闂鏄劇ず錛
P1 &= 0xf0; //琛屽彿絝鍙f竻鈼
RCLK = 1; //鏄劇ず鏁版嵁鎵撳叆杈撳嚭閿佸瓨鍣
P1 |= i; //鍐欏叆琛屽彿
RCLK = 0; //閿佸瓨鏄劇ず鏁版嵁
G = 0; //鎵撳紑鏄劇ず
}