2024年10月12日 星期六

[8051] 注意檢查副程式和主程式對暫存器的設定,以TMOD為例

參考教材:單晶片微處理機實習,黃嘉輝,台科大出版

本篇文章主要是將串列傳輸收到的資料顯示在LCD上,參考第六章實習四、實習五、以及實習十四的範例。

注意!我們在寫程式時,常常會把兩支已寫好的範例組合起來,但因為忽略可能有些暫存器在不同範例中有重複使用到,造成執行結果不如預期,以下面程碼為例,在24行和66行都有設定TMOD,造成不小心修改到計時器的模式,而造成傳輸速率已經不是原來的設定值。

程式碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <regx51.h>

unsigned char SendBuf[]={0,1,2,3,4,5,6,7,8,9};
// 0-9七段顯示器資料區
unsigned char code table[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char buf;

// 使用函數的設定區
extern void LCD_Init(void);
extern void LCD_Out(unsigned char x, unsigned char y, unsigned char *text);
extern void LCD_Out_Cp(unsigned char *text);
extern void LCD_Chr(unsigned char x, unsigned char y, unsigned char c);
extern void LCD_Chr_Cp(unsigned char c);
extern void LCD_Cmd(unsigned char cmd);
extern void LCD_GotoXY(unsigned char x, unsigned char y);

// 使用命令的設定區
extern unsigned char LCD_CURSOR_ON;
extern unsigned char LCD_CURSOR_OFF;

void init_UART(unsigned int baudrate)
{
		SCON=0x52;
		TMOD=0x20;
		TH1=256-((11059200/384)/baudrate);
		TL1=TH1;
		TR1=1;
}

void Delay_ms(unsigned int count) 	//延遲count*1ms副程式
{
		TL0=(8192-1000)%32;
		TH0=(8192-1000)/32;
		TR0=1;
		while(count)
		{
				while(TF0==0);
				TL0=(8192-1000)%32;
				TH0=(8192-1000)/32;
				TF0=0;
				count--;
		}
		TR0=0;
}

void UART_int(void) interrupt 4		//串列中斷函式	
{
	if(RI==1)												//是不為接收中斷?
	{
		RI=0;													//完成後清除RI
		buf=SBUF;
		//將接到的資料給buf
		LCD_Chr(1,1, buf+0x30);  					//將接收到的資料送往顯示
	}
	else
		TI=0;													//如果是傳送中斷,則清除TI,下次才方再傳送
}	

void main(void)
{
			unsigned int i;
			init_UART(9600);						//設定串列傳輸模式-9600bps
			ES=1;												//開啟串列中斷
			EA=1;	                      //開啟總中斷
	
			TMOD=0x00;									// 設定 T0 為 mode0
			LCD_Init();									// LCD 初始化
			LCD_Cmd(LCD_CURSOR_ON);			// 將游標打開
			LCD_Chr(1,7,'8');						// LCD 在(1,7)位置顯示8
			LCD_Chr_Cp('0');						// LCD 在(1,8)位置顯示0
			LCD_Out_Cp("51");						// LCD 在(1,9)位置顯示51
			Delay_ms(2000);
			LCD_Cmd(LCD_CURSOR_OFF);		// 將游標關閉
			LCD_Out(2,3,"LCD Display");	// LCD 在(2,3)位置顯示LCD Display
			Delay_ms(2000);

			while(1)
			{
				for(i=0;i<10;i++)
				{
					SBUF=SendBuf[i];					//傳送0-9
					Delay_ms(2000);
				}
			}
}

執行結果:

程式執行結果,有許多亂碼產生,我們將程式中第66行的程式註解後,動作就正常。



沒有留言:

張貼留言