A. 交通燈 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;
}
=====================================================================
坐等拿分!
B. 怎樣在C語言中使用中斷函數
首先你要寫中斷函數
然後在主程序中像調用子函數一樣調用就可以了
舉個例子吧
#define uchar unsigned char
#define uchar unsigned char
sbit D1=P1^0;
uchar aa;
void init()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void main()
{
init();
while(1)
{
if(aa==20)
{
D1=~D1;
aa=0;
}
}
}
void T0time()interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
aa++;
}
C. 單片機C語言中斷函數的定義形式是怎樣的
形式如下:
void 中斷名(void) inerrupt 中斷號 using 工作寄存器組
比如外部中斷0
void ext0(void) interrupt 0 using 1 //後面的using 1可以省略,預設為0
定時器1
void t1isr() interrupt 3
(3)c語言中斷函數問題擴展閱讀:
單片機內部結構
1、CPU
它的名字沒有改,還是稱為CPU(Central Processing Unit)。它是單片機的核心部件,包括運算器和控制器。
運算器既是算術邏輯單元ALU(Arithmetic logic Unit),其功能是進行算術運算和邏輯運算。
控制器一般由指令寄存器、指令解碼器、時序電路和控制電路組成。其作用是完成取指令、將指令解碼形成各種微操作並執行指令,同時控制計算機的各個部件有條不紊地工作。
2、單片機內部結構之一ROM
「硬碟」,改了名字,稱為程序存儲器,也叫只讀存儲器。用ROM(Read only memery)表示。其作用和計算機的硬碟差不多,用來存放用戶編寫的程序。特點是:掉電後不會丟失數據(程序)。
D. 51的C語言中斷是函數,那這個中斷是否可以調用如果能,怎麼調用
51的C語言中斷是函數,那這個中斷是否可以調用?如果能,怎麼調用?
只從計算機原理來講,是可以的。
理論上,中斷函數也是一個程序的入口,只要把程序指令指針指向這個中斷的入口地址,
就可以執行相應的代碼,從這個角度來講,是可操作的。
但在實際問題處理中,通常不行,因為中斷是提供給系統處理應急事件的,
並非設計來作為常規函數呼叫。
如果只是想要使用中斷處理中的某些功能,可把那些功能封裝為獨立的函數,
供給中斷處理和一般流程來調用。
應用程序直接調用中斷,是有違中斷設計的初衷的,
不建議這樣使用,易導致原本正常的流程的莫名異常,
因為調用中斷處理,會佔用中斷的相關資源,導致正常的中斷無法執行,出現異常。
E. 單片機c語言中斷函數
using1
表示用寄存器工作組1.。其實不加也可以,在c語言中,是自動分配寄存器的,所以可以不加。。
interrupt
1
後面數字是中斷源
,表示啟用中斷源1(定時器0).(51單片機里有5個中斷源)
F. C語言中斷/定時的疑問
中斷函數是不需要額外通過代碼調用的
當中斷條件滿足,單片機會打斷當前執行的語句,跳轉到中斷函數,然後執行完中斷函數後,再次返回之前被打斷的語句繼續執行
中斷函數中,每次都會對定時器重新初始化,即頭兩句對TH1和TL1的賦值,這樣每50ms會再次進入一次中斷函數.每20次進入中斷,即經過了1秒,然後對全局變數miao自增1
而main函數則是不斷對變數miao進行輸出
G. 單片機中斷函數C語言的問題
蜂鳴器響,需要每隔約 2ms 令 BEEP 翻轉一次。
這就需要用 T1 定時 2ms。
如果需要低頻,就需要更長的的定時。
參考程序如下:
H. 單片機c語言中斷函數
這是單片機C語言中斷函數的編程格式,()後面的只是告訴編譯系統該函數是一個中斷函數,具體的執行還是按照C語言函數的執行方式去執行。
I. 單片機c語言中斷函數中可以定義形參嗎
單片機c語言中斷函數中可以定義形參,但一般不需要這樣做。
中斷函數的定義格式如下:
函數類型
函數名
(形參)
interrupt
N
using
n
我們平時用的大多是KEIL編譯器,對於KEIL編譯器來說,中斷函數不需要輸入,也不返回參數,因此這里的函數類型和函數形參都應該為
void
類型。
n
表示使用的寄存器組,為
0---3,using是一個選項,可以省略,如果省略,有編譯器來選擇一個寄存器組作為絕對寄存器組。
N
表示中斷號(這個不能省略,而且比較重要),下列出來普通51單片機的中斷號和中斷源的對應關系:
中斷號
中斷源
0
外部中斷0
1
定時器0中斷
2
外部中斷1
3
定時器1中斷
4
串列口中斷
5
定時器2中斷
總之,一般來說,中斷函數不需要定義形參。
J. 51單片機c語言中斷函數不能進行參數傳遞,是什麼意思,誰能解釋一下
是指中斷處理函數不能有輸入參數也不能有函數返回。因為中斷都是些硬體自動調用,沒有程序去給他傳遞參數,也沒有硬體去接收參數。
不過x86計算機的軟中斷可以有參數傳遞,不過他是用寄存器傳遞的。