#include <reg51.h>
#define lcd_clear_all 0x01
#define lcd_disp_off 0x08
#define lcd_disp_on 0x0C
#define serial_recv 0
#define serial_send 1
unsigned char xdata A0 _at_ 0xC080; // LCD A0 address
unsigned char xdata A1 _at_ 0xC081; // LCD A1 address
unsigned char xdata A2 _at_ 0xC082; // LCD A2 address
unsigned char xdata AA _at_ 0xC040; /* Analog address */
sbit P1_0 = P1^0; sbit P1_1 = P1^1; sbit P1_2 = P1^2; sbit P1_3 = P1^3;
sbit P1_4 = P1^4; sbit P1_5 = P1^5; sbit P1_6 = P1^6; sbit P1_7 = P1^7;
bit serial_mode = serial_recv; // To represent serial send or receive
bit conn = 0;
bit flag_packet_start = 0;
bit flag_data_start = 0;
bit flag_msg = 0;
bit flag_star = 0;
bit flag_send_adc_on = 0;
bit flag_send_adc_off = 0;
bit flag_sampling = 0;
bit flag_1sec = 0;
bit flag_adc = 0;
bit flag_sample = 0;
bit flag_5sec = 0;
unsigned char serial_data; // Received data from serial line
unsigned char sdata[17];
unsigned char sd_index = 0;
unsigned char queue[20];
unsigned char front = 0, rear = 0;
unsigned char hour= 0, minute = 0, second = 0; // time
unsigned char optime[10] = "00 00 00 ";
unsigned char star = '/';
unsigned char adc_value[3] = "00";
unsigned short sample_time = 100;
unsigned short timer_count = 0;
unsigned short timer_count2 = 0;
unsigned short timer_count3 = 0;
//////////////////////////////////////////////////
void timer_init(void);
void ex_init(void);
void lcd_init(void);
void serial_init(void);
void delay(unsigned int count);
void lcd_busy_check(void);
void lcd_cmd_write(unsigned char cmd);
void lcd_char_out(char ch);
void lcd_string_out(char *str);
void lcd_gotoxy(unsigned char x, unsigned char y);
void serial_char_out(char ch);
void serial_string_out(char *str);
unsigned char hex_out(unsigned char hex_in);
void show_timer(void);
void led_operation(unsigned char op);
void str_cpy(unsigned char *dest, unsigned char *src);
void str_cat(unsigned char *dest, unsigned char *src);
void set_extern_font(void);
void Inqueue(unsigned char ch);
unsigned char Dequeue(void);
void make_spacket(unsigned char c, unsigned char *data_);
void run_serial_com(unsigned char cmd);
unsigned short a_to_i(unsigned char *str);
//////////////////////////////////////////////////
/*/////////////////////////////////////////////////
//// M-A-I-N
*//////////////////////////////////////////////////
void main(void)
{
unsigned char command = 0;
unsigned char analog_in;
unsigned char analog_high;
unsigned char analog_low;
set_extern_font();
lcd_init();
lcd_cmd_write(lcd_clear_all);
lcd_cmd_write(lcd_disp_on);
serial_init();
timer_init();
ex_init();
P1 = 0x00;
delay(3000);
P1 = 0xff;
// lcd line 1
lcd_gotoxy(0, 0); lcd_string_out("00 00 00 ID:0842");
lcd_gotoxy(2, 0); lcd_char_out(0x01);
lcd_gotoxy(5, 0); lcd_char_out(0x02);
lcd_gotoxy(8, 0); lcd_char_out(0x03);
// lcd line 2
lcd_gotoxy(0, 1); lcd_string_out("/ADC0x00 100 OFF");
while (1)
{
//----------------------------------------
// STRING TIMER
if (flag_1sec == 1) {
second++;
if (second >= 60) {
minute++;
second = 0;
}
if (minute >= 60) {
hour++;
minute = 0;
}
flag_1sec = 0;
show_timer(/*optime*/);
// send timer to serial
/*sdata=*/make_spacket('T', optime);
serial_string_out(sdata);
}
//----------------------------------------
// ADC ON
if (flag_adc == 1 && flag_msg == 0) {
// send adc on
if (flag_send_adc_on == 1) {
flag_send_adc_on = 0;
/*sdata=*/make_spacket('A', "100");
serial_string_out(sdata);
delay(100);
}
// run star
if (flag_star == 1) {
unsigned char temp[2];
flag_star = 0;
lcd_gotoxy(0, 1); lcd_char_out(star);
// send star to serial
if (star == 0x00) temp[0] = '\\';
else temp[0] = star;
temp[1] = 0;
/*sdata=*/make_spacket('R', temp);
serial_string_out(sdata);
}
// run adc value
if (flag_sampling == 1) {
flag_sampling = 0;
AA = 0x00; delay(100);
analog_in = (AA);
analog_low = 0x0F & analog_in;
analog_high = 0x0F & (analog_in >> 4);
adc_value[0] = hex_out(analog_high); //display upper 4 bit of value
adc_value[1] = hex_out(analog_low); //display lower 4 bit of value
lcd_gotoxy(6, 1); lcd_string_out(adc_value);
// send adc value to serial
/*sdata=*/make_spacket('V', adc_value);
serial_string_out(sdata);
}
}
//----------------------------------------
// ADC OFF
if (flag_send_adc_off == 1 && flag_msg == 0) {
flag_send_adc_off = 0;
/*sdata=*/make_spacket('a', 0);
serial_string_out(sdata);
delay(100);
}
//----------------------------------------*/
//----------------------------------------
// RECEIVE SERIAL PACKET
serial_data = Dequeue();
if (serial_data == '\0') continue;
if (serial_data == 0x02) { // packet start
flag_packet_start = 1;
continue;
}
else if (serial_data == '<') { // data start
flag_data_start = 1;
continue;
}
else if (serial_data == '>') { // data end
flag_data_start = 0;
sdata[sd_index] = '\0';
sd_index = 0;
continue;
}
else if (serial_data == 0x03) { // packet end
Dequeue();
flag_packet_start = 0;
run_serial_com(command);
}
// get command
if (flag_packet_start && !flag_data_start) {
command = serial_data;
}
// get data
else if (flag_packet_start && flag_data_start) {
sdata[sd_index] = serial_data;
sd_index++;
}
//----------------------------------------*/
if (flag_msg == 1 && flag_5sec == 1) {
flag_msg = 0;
flag_5sec = 0;
lcd_gotoxy(0, 1);
lcd_char_out(star);
lcd_string_out("ADC0x");
lcd_string_out(adc_value);
lcd_string_out(" 100 ");
lcd_string_out("OFF");
}
} // end while
}
/***************************************************
* EXTERNAL0 INTERRUPT
*/
void EX0_int(void) interrupt 0 {
EX0 = 0;
if (flag_adc == 0) { // ADC OFF -> ON
flag_adc = 1;
flag_send_adc_on = 1;
A0 = 0xCD;
while ((A2)&0x80); A1 = ' ';
while ((A2)&0x80); A1 = 'O';
while ((A2)&0x80); A1 = 'N';
}
else if (flag_adc == 1) { // ADC ON -> OFF
flag_adc = 0;
flag_send_adc_off = 1;
A0 = 0xCD;
while ((A2)&0x80); A1 = 'O';
while ((A2)&0x80); A1 = 'F';
while ((A2)&0x80); A1 = 'F';
}
}
/***************************************************
* TIMER 0 INTERRUPT
*/
void timer_int_0(void) interrupt 1 { // Timer 0 Interrupt
TH0 = 0xfc; // 0.001 sec
TL0 = 0x65; // Internal Clock
timer_count++;
timer_count2++;
if (flag_adc == 1) { // ADC ON
// star character
if (timer_count == 1 || timer_count == 500) {
star = '/'; flag_star = 1;
}
else if (timer_count == 125 || timer_count == 625) {
star = '-'; flag_star = 1;
}
else if (timer_count == 250 || timer_count == 750) {
star = 0x00; flag_star = 1;
}
else if (timer_count == 375 || timer_count == 875) {
star = '|'; flag_star = 1;
}
// sample time
if ((timer_count%sample_time) == 0)
flag_sampling = 1;
}
if (timer_count == 1000 && flag_msg == 1)
timer_count3++;
if (timer_count == 1000 && flag_msg == 1 && timer_count3 == 5) {
timer_count3 = 0;
flag_5sec = 1;
}
if (timer_count >= 1000) { // 1 sec = 0.001 * 1000
timer_count = 0;
flag_1sec = 1;
}
if (timer_count2 >= 499) { // 500 ms
timer_count2 = 0;
EX0 = 1;
}
}
/**************************/
/***************************************************
* SERIAL INTERRUPT
*/
void serial_int(void) interrupt 4 // Serial Interrupt
{
// if (serial_mode == serial_recv) // Serial receive interrupt
if (RI == 1) {
Inqueue(SBUF);
RI = 0;
}
else if (TI == 1) {
TI = 0;
serial_mode = serial_recv;
}
// TI = 0;
// RI = 0;
}
/**************************/
/**************************************************
* TIMER INIT
*/
void timer_init(void) {
TH0 = 0xFC; // 1 ms
TL0 = 0x65;
TR0 = 1;
ET0 = 1;
}
/**************************/
/**************************************************
* EX INIT
*/
void ex_init(void) {
EX0 = 1;
IT0 = 1;
PX0 = 1;
EA = 1;
}
/**************************/
/***************************************************
* DELAY
*/
void delay(unsigned int count) {
while(count--);
}
/**************************/
/***************************************************
* LCD INIT
*/
void lcd_init(void) {
delay(5000);
A0 = 0x38; delay(500); // LCD function set
A0 = 0x0f; delay(500); // Display on
A0 = 0x01; delay(500); // Display clear
A0 = 0x06; // Entry mode set
}
/**************************/
/**************************************************
* LCD BUSY CHECK
*/
void lcd_busy_check(void) {
unsigned char d;
do {
d = (A2); // LCD의 값을 읽어 변수 d 에 저장
} while(d & 0x80);
}
/**************************/
/**************************************************
* LCD CMD WRITE
*/
void lcd_cmd_write(unsigned char cmd) {
lcd_busy_check();
A0 = cmd;
delay(1);
}
/**************************/
/**************************************************
* LCD CHAR OUT
*/
void lcd_char_out(char ch) {
lcd_busy_check();
A1 = ch;
}
/**************************/
/**************************************************
* LCD STRING OUT
*/
void lcd_string_out(char *str) {
while(*str) {
lcd_char_out(*str);
str++;
}
}
/**************************/
/**************************************************
* LCD GOTO XY
*/
void lcd_gotoxy(unsigned char x, unsigned char y) { // Start address is 0, 0
unsigned location;
switch(y) {
case (0) : // LCD line 1, First address 0x80
location = 0x80 + x;
lcd_cmd_write(location); break;
case (1) : // LCD line 2, First address 0xC0
location = 0xC0 + x;
lcd_cmd_write(location); break;
case (2) : // LCD line 3, First address 0x94
location = 0x94 + x;
lcd_cmd_write(location); break;
case (3) : // LCD line 4, First address 0xD4
location = 0xD4 + x;
lcd_cmd_write(location); break;
}
}
/**************************/
/**************************************************
* SERIAL INIT
*/
void serial_init(void) {
/* ES = 1; // Serial Interrupt Enable
SCON = 0x50; // Serial Mode 1(Async 10 bit), REN = 1
PCON = 0x00; // SMOD = 1, 1은 2배 전송 속도
TCON = 0x01;
TMOD = 0x21; // Timer 1 Mode는 2로 설정
PS = 1; // Serial Port Interrupt Priority를 High로
TH1 = 0xFD; // Bps 설정, SMOD를 고려, 19200 bps = FD
// SMOD = 0인 경우, bps = (1/32) * 오실레이터 주파수/(12 * (256-TH1값))
// SMOD = 1인 경우, bps = (1/16) * 오실레이터 주파수/(12 * (256-TH1값))
// TH1값 = 256 - (오실레이터 주파수/(Bps값*16*12))
// 비트 듀래이트로 썼기 때문에 , 다른곳에서는 못 TMa
TR1 = 1; // Timer 1을 Start
TI = 0; // Initial TI for Send Interrupt Occur
RI = 0; // Initial RI for Receive Interrupt Occur
// TI, RI는 인터럽트가 발생되면 1 이
// 되기 때문에 인터럽트 후에 Clear 함
// TI = 1 이면 클리어,
// 인터럽트 후에는 클리어 해준다.
*/
ES =1; //enable serial interrupt
PCON = 0x00; //baud rate 9600
SCON = 0x50;
TCON = 0x01; //edge level detect
TMOD = 0x21; //timer 0 16bit timer 1 8bit mode
PS =1; // serial interrupt priolity
TH1 = 0xfd;
TR1 = 1;
RI =0;
TI =0;
}
/**************************/
/**************************************************
* SERIAL CHAR OUT
*/
void serial_char_out(char ch) { // 1 Byte send through serial line
serial_mode = serial_send;
SBUF = ch;
while (serial_mode) ;
}
/**************************/
/**************************************************
* SERIAL STRING OUT
*/
void serial_string_out(char *str) { // String send through serial line
while (*str) {
serial_char_out(*str);
str++;
}
}
/**************************/
/**************************************************
* HEX OUT
*/
unsigned char hex_out(unsigned char hex_in) {
if (hex_in < 10)
return hex_in + 0x30;
else
return hex_in + 0x41 - 0x0A;
}
/**************************/
/**************************************************
* SHOW TIMER
*/
void show_timer(void) {
//-------------------- hour
if(hour < 10) {
optime[0] = 0 + '0';
optime[1] = hour + '0';
}
else {
optime[0] = (hour/10) + '0';
optime[1] = (hour%10) + '0';
}
optime[2] = 0x01;
//-------------------- minute
if(minute < 10) {
optime[3] = 0 + '0';
optime[4] = minute + '0';
}
else {
optime[3] = (minute/10) + '0';
optime[4] = (minute%10) + '0';
}
optime[5] = 0x02;
//-------------------- second
if(second < 10) {
optime[6] = 0 + '0';
optime[7] = second + '0';
}
else {
optime[6] = (second/10) + '0';
optime[7] = (second%10) + '0';
}
optime[8] = 0x03;
optime[9] = 0;
lcd_gotoxy(0, 0);
lcd_string_out(optime);
optime[2] = ':'; optime[5] = ':'; optime[8] = 0;
}
/**************************/
/**************************************************
* LED OPERATION
*/
void led_operation(unsigned char op) {
switch (op) {
case '8': P1 = 0x00;return;
case '*': P1 = 0xff;return;
case '7': P1_7 = 0; return;
case '&': P1_7 = 1; return;
case '6': P1_6 = 0; return;
case '^': P1_6 = 1; return;
case '5': P1_5 = 0; return;
case '%': P1_5 = 1; return;
case '4': P1_4 = 0; return;
case '$': P1_4 = 1; return;
case '3': P1_3 = 0; return;
case '#': P1_3 = 1; return;
case '2': P1_2 = 0; return;
case '@': P1_2 = 1; return;
case '1': P1_1 = 0; return;
case '!': P1_1 = 1; return;
case '0': P1_0 = 0; return;
case ')': P1_0 = 1; return;
}
}
/**************************/
/**************************************************
* STRING COPY
*
void str_cpy(unsigned char *dest, unsigned char *src) {
while ( (*dest=*src) !='\0')
{
dest++; src++;
}
*dest = '\0';
}
/**************************/
/**************************************************
* STRING CAT
*
void str_cat(unsigned char *dest, unsigned char *src) {
while (*dest)
dest++;
while (*src)
*dest++ = *src++;
*dest = '\0';
}
/**************************/
/**************************************************
* SET EXTERN FONT
*/
void set_extern_font(void) {
//set extern charicter 0x00
lcd_cmd_write(0x40);
lcd_char_out(0x00); lcd_char_out(0x10); lcd_char_out(0x08);
lcd_char_out(0x04); lcd_char_out(0x02); lcd_char_out(0x01);
lcd_char_out(0x00); lcd_char_out(0x00);
//set extern char 0x01
lcd_cmd_write(0x48);
lcd_char_out(0x05); lcd_char_out(0x05); lcd_char_out(0x05);
lcd_char_out(0x0d); lcd_char_out(0x13); lcd_char_out(0x13);
lcd_char_out(0x13); lcd_char_out(0x00);
//set extern char 0x02
lcd_cmd_write(0x50);
lcd_char_out(0x0a); lcd_char_out(0x0e); lcd_char_out(0x0e);
lcd_char_out(0x1f); lcd_char_out(0x04); lcd_char_out(0x14);
lcd_char_out(0x1f); lcd_char_out(0x00);
//set extern char 0x03
lcd_cmd_write(0x58);
lcd_char_out(0x04); lcd_char_out(0x1f); lcd_char_out(0x04);
lcd_char_out(0x0e); lcd_char_out(0x11); lcd_char_out(0x04);
lcd_char_out(0x1f); lcd_char_out(0x00);
}
/**************************/
/**************************************************
* INQUEUE
*/
void Inqueue(unsigned char ch) {
if( ((front + 1) % 20) == rear )
return; // queue is full
queue[front] = ch;
front = (front + 1) % 20;
}
/**************************/
/**************************************************
* DEQUEUE
*/
unsigned char Dequeue(void) {
unsigned char temp;
if(front == rear) {
return 0; //queue is empty
}
temp = queue[rear];
rear = (rear + 1) % 20;
return temp;
}
/**************************/
/**************************************************
* MAKE SERIAL PACKET
*/
void make_spacket(unsigned char c, unsigned char *data_)
{
unsigned char len;
sdata[0] = 0x02;
sdata[1] = c;
sdata[2] = '<';
for (len=0; data_[len] != 0; len++) {
sdata[3+len] = data_[len];
}
sdata[3+len] = '>';
sdata[4+len] = 0x03;
sdata[5+len] = '\n';
sdata[6+len] = 0;
}
/**************************/
/**************************************************
* RUN SERIAL COMMAND
*/
void run_serial_com(unsigned char cmd)
{
switch (cmd) {
case 'I': // request client id
/*sdata=*/make_spacket('I', "0842");
serial_string_out(sdata);
break;
case 'E': // operate led
led_operation(sdata[0]);
break;
case 'A': // ADC ON
flag_adc = 1;
flag_send_adc_on = 1;
lcd_gotoxy(13, 1);
lcd_string_out(" ON");
break;
case 'a': // ADC OFF
flag_adc = 0;
flag_send_adc_off = 1;
lcd_gotoxy(13, 1);
lcd_string_out("OFF");
break;
case 'S': // Sampling Time
lcd_gotoxy(9, 1);
lcd_string_out(" ");
delay(100);
lcd_gotoxy(9, 1);
lcd_string_out(sdata);
sample_time = a_to_i(sdata);
break;
case 'i': // LCD init
lcd_init();
// lcd line 1
lcd_gotoxy(0, 0); lcd_string_out("00 00 00 ID:0842");
lcd_gotoxy(2, 0); lcd_char_out(0x01);
lcd_gotoxy(5, 0); lcd_char_out(0x02);
lcd_gotoxy(8, 0); lcd_char_out(0x03);
// lcd line 2
lcd_gotoxy(0, 1); lcd_string_out("/ADC0x00 100 OFF");
break;
case 'M': // Message
flag_msg = 1;
lcd_gotoxy(0, 1);
lcd_string_out("MSG : ");
lcd_string_out(sdata);
}
}
/**************************/
unsigned short a_to_i(unsigned char *str)
{
unsigned short result = 0;
while (*str)
result = result*10 + ((*str++) - '0');
return result;
}