2024年10月12日 星期六

[8051] 實作檢查碼,若有錯則顯示錯誤

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

前一篇文章:設計簡單的通訊協定以POS機串接的通訊為例

程式碼:

  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
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <regx51.h>

#define STX 0x02
#define ETX 0x03
unsigned char SendBuf[]="51015100peanut10";
unsigned char ReceiveBuf[16];
int receive_cnt=0;
unsigned char buf;
int count=1000;									//1秒=1000*1ms
int on_line_sec=0;							//連線秒數
int on_line_status=0;						//onlne or offline
int is_receive=0;								//是否有接收
int is_check=0; 								//檢查碼
unsigned char calculateLRC(unsigned char *d, int length);

// 使用函數的設定區
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;
extern unsigned char LCD_CLEAR;

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

void T0_int(void) interrupt 1
{
	TL0=(8192-1000)%32;						//重設設定值
	TH0=(8192-1000)/32;
	if(count==0)					//連線已經有1秒了嗎?
	{
		if(on_line_status)
			{
				on_line_sec++;
				on_line_sec%=100;
				LCD_Chr(2,16, on_line_sec%10+0x30);    //將接收到的資料送往顯示
				LCD_Chr(2,15, on_line_sec/10+0x30);    //將接收到的資料送往顯示
			}
		if(!is_receive)
			{
				LCD_Cmd(LCD_CLEAR);
				LCD_Out(2,1,"offline");
				on_line_status=0;
				on_line_sec=0;
			}
		is_receive=0;	 
		count=1000;									//1秒count
	}
	else
		count--;										//count每1ms減1
}

void UART_int(void) interrupt 4		//串列中斷函式	
{
	if(RI==1)												//是不為接收中斷?
	{
		RI=0;													//完成後清除RI
		buf=SBUF;											//將接到的資料給buf
		if(is_check){
			is_check=0;
			if(buf != calculateLRC(ReceiveBuf, 16))
				LCD_Out(2,1,"check err");
		}
		else if(buf == STX)
			receive_cnt=0;
		else if (buf == ETX)
		{
			LCD_Out(1,1,ReceiveBuf);
			is_check=1;
		}
		else
		{			
			ReceiveBuf[receive_cnt++]=buf;
			receive_cnt%=16;
		}
		is_receive=1;
		if(!on_line_status){
			on_line_sec=0;
			on_line_status=1;
			LCD_Out(2,1,"online ");
			count=1000;	
		}
	}
	else
		TI=0;													//如果是傳送中斷,則清除TI,下次才方再傳送
}

void Delay_ms(unsigned int count) 						//延遲count*1ms函式
{
				unsigned int i,j;
				for(i=0;i<count;i++)
								for(j=0;j<123;j++);
}

unsigned char calculateLRC(unsigned char *d, int length)
{
	  unsigned char LRC = 0;  // LRC 的初始值
		int i;
    for (i = 0; i < length; i++) {
        LRC ^= d[i];  // 進行 XOR 運算
    }
    LRC ^= ETX;  // XOR 運算 ETX
    return LRC;
}

void main(void)
{
			unsigned int i;
			init_UART(9600);						//設定串列傳輸模式-9600bps
			ES=1;												//開啟串列中斷
			ET0=1;											//啟動計時器1
			EA=1;	                      //開啟總中斷
			TR0=1; 											//啟動計時器
	
			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
			LCD_Cmd(LCD_CURSOR_OFF);		// 將游標關閉
			LCD_Out(1,1," ");	
			LCD_Out(2,1,"offline");			// LCD 在(2,1)位置顯示offline
			LCD_Out(2,15,"00");

			while(1)
			{
				SBUF=STX;
				Delay_ms(10);
				for(i=0;i<16;i++)
				{
					SBUF=SendBuf[i];					//傳送0-9
					Delay_ms(10);
				}
				SBUF=ETX;
				Delay_ms(10);
				SBUF=calculateLRC(SendBuf, 16);
				Delay_ms(1000);
			}
}

執行結果:

若把第149行改為SBUF=calculateLRC(SendBuf, 16)+1;
執行結果:


沒有留言:

張貼留言