📄 lcd8.c
字号:
/*
SWR Neter board LCD routines
This is polling driver with 8-bit interface
Juha Niinikoski OH2NLT 26.01.2004
Serial I/O removed. All output functions collected here.
Bar graph modified for SOLOMON LM1125SYLU1 display 27.01.2004
Cross bar fwd / rev power meter 27.01.2004
S-meter bar display, leading zero blanc for freq display 27.04.2004
*/
/* 2 * 16 LCD display memory layout */
#define LINE1 0x00 /* line 1 start address */
#define LINE2 0x40 /* line 2 start address */
#define CURSET 0x80 /* set memory cursor */
#define CLEAR 0x01 /* clear display */
#define ADRSET 0x40 /* set cgram address */
void clk_lcd(unsigned char ldata) // set data & clock both lcd controllers
{
LCD_DATA = ldata;
LCD_E = 1;
asm("nop");
asm("nop");
asm("nop");
LCD_E = 0;
}
void wait_lcd_rdy(void) // wait until lcd module is ready
{
unsigned char BF_AC; // BF flag & address counter
BF_AC = 0x80; // set busy for first round
LCD_TRIS = 0xFF; // make data port input
LCD_RW = 1; // read
LCD_RS = 0; // command mode
while(BF_AC & 0x80)
{
asm("nop"); // 18.01.2004 for slow display
LCD_E = 1;
asm("nop");
asm("nop");
asm("nop");
BF_AC = LCD_DATA;
LCD_E = 0;
}
LCD_RW = 0;
LCD_RS = 1;
LCD_TRIS = 0x00; // return to write mode
}
void set_cur_lcd(unsigned char cur) // set cursor position at selected display
{
wait_lcd_rdy( );
LCD_RS = 0; // switch command mode
clk_lcd(cur | CURSET); // set cursor command + cursor position
LCD_RS = 1; // back to data mode
}
void clear_lcd(void) // clear selected display
{
wait_lcd_rdy( );
LCD_RS = 0; // switch command mode
clk_lcd(CLEAR); // clear display. Display going to be busy 1,6 mS
LCD_RS = 1; // back to data mode
}
void initlcd(void) // init selected LCD controller
{
LCD_RS = 0; // set command mode
LCD_RW = 0;
clk_lcd(0x38); // write init data with delays
delay(5);
clk_lcd(0x38);
delay(1);
clk_lcd(0x38); //8-bit, 2 rows, 5x7 matrix, display on
delay(1); //cursor off, no blink
clk_lcd(0x0C);
delay(1);
clk_lcd(0x01);
delay(2);
clk_lcd(0x06); // increment, no display shift
delay(1);
LCD_RS = 1; // set data mode
}
void lcdoutch( unsigned char lcd_char ) // output character to selected display
{
wait_lcd_rdy();
clk_lcd(lcd_char);
}
/* HD44780 character generator routines */
/* modified for SOLOMON LM1125SYLU1 display */
const char Blockslr[6] = {0x20, 0x00, 0x00, 0x01, 0x01, 0x02}; // blocks for L to R bar graph
const char Blocksrl[6] = {0x20, 0x03, 0x03, 0x04, 0x04, 0x02}; // R to L
void set_cgram(unsigned char adr, unsigned char dta) // set cgram address & data
{
wait_lcd_rdy( );
LCD_RS = 0; // switch command mode
adr = adr & 0x3F;
clk_lcd(adr | ADRSET); // set cgram address command + address
LCD_RS = 1; // back to data mode
wait_lcd_rdy();
clk_lcd(dta);
clear_lcd(); // back to normal mode (clear LCD)
}
void set_ch_bits(char dta, char cnt) // set chgen bits. Data, number of sets
{
char x;
for(x=0; x<cnt; x++)
{
wait_lcd_rdy();
clk_lcd(dta);
}
}
void set_chgen(void) // write bar symbols to HD44780 RAM chgen
{
wait_lcd_rdy( );
LCD_RS = 0; // switch command mode
clk_lcd(0 | ADRSET); // set cgram address command + address
LCD_RS = 1; // back to data mode
set_ch_bits(0, 1);
set_ch_bits(0x10, 5); // CGRAM 00 Blocks L > R
set_ch_bits(0, 2);
set_ch_bits(0, 1);
set_ch_bits(0x14, 5); // CGRAM 01
set_ch_bits(0, 2);
set_ch_bits(0, 1);
set_ch_bits(0x15, 5); // CGRAM 02 "Full block"
set_ch_bits(0, 2);
set_ch_bits(0, 1);
set_ch_bits(0x01, 5); // CGRAM 03 Blocks R > L
set_ch_bits(0, 2);
set_ch_bits(0, 1);
set_ch_bits(0x05, 5); // CGRAM 04
set_ch_bits(0, 2);
set_ch_bits(0x08, 7); // CGRAM 05 spare
set_ch_bits(0, 1);
set_ch_bits(0, 3); // CGRAM 06 S-meter scale dot
set_ch_bits(0x10, 1);
set_ch_bits(0, 4);
set_ch_bits(0, 2); // CGRAM 07 S-meter scale bar
set_ch_bits(0x10, 3);
set_ch_bits(0, 3);
clear_lcd(); // back to normal mode (clear LCD)
}
// Meter constants
#define DISP_LEN 16 // display lemgth (char)
#define FONT_W 5 // font width
#define MAX_GRAPH (DISP_LEN * FONT_W) // graph length in pixels (5*16 = 80)
const char scale_dots[16] = {6,32,6,32,6,32,6,32,7,32,7,32,7,32,7,32};
// draw S-meter, scale = 0...80
// buffer is used to avoid LCD flicker
void draw_s_meter(char len)
{
char x;
char whole;
char part;
char idx;
char bar_buffer[DISP_LEN]; // display buffer
if(len > MAX_GRAPH) // cut to max
len = MAX_GRAPH;
whole = len / FONT_W; // calculate graph
part = len % FONT_W;
idx = 0;
for(x=0; x<DISP_LEN; x++) // copy scale dots to buffer
{
bar_buffer[idx] = scale_dots[x];
idx++;
}
idx = 0; // draw graph to buffer
while(whole > 0)
{
bar_buffer[idx] = 0x02; // draw full blocks
idx++;
whole--;
}
if(part > 0)
bar_buffer[idx] = Blockslr[part]; // draw partial block to buffer
for(x=0; x<DISP_LEN; x++) // print meter buffer to LCD
{
lcdoutch(bar_buffer[x]);
}
}
// draw graph
// 0 = left to rigth, 1 = rigth to left
void draw_bar(char len, char dir) // draw bar graph
{
char x;
char whole;
char part;
char l;
char idx;
char bar_buffer[DISP_LEN]; // display buffer
if(len > MAX_GRAPH) // cut to max
len = MAX_GRAPH;
l = DISP_LEN;
whole = len / FONT_W; // calculate graph
part = len % FONT_W;
if(dir == 0) // L to R
{
idx = 0;
while(whole > 0)
{
bar_buffer[idx] = 0x02; // draw full blocks
idx++;
whole--;
l--;
}
if(part > 0)
{
bar_buffer[idx] = Blockslr[part]; // draw partial block
idx ++;
l--;
}
for(x=0; x<l; x++) // clear rest of the line
{
bar_buffer[idx] = 0x20;
idx++;
}
}
else // draw from R to L
{
idx = DISP_LEN - 1;
while(whole > 0)
{
bar_buffer[idx] = 0x02; // draw full blocks
idx--;
whole--;
l--;
}
if(part > 0)
{
bar_buffer[idx] = Blocksrl[part]; // draw partial block
idx --;
l--;
}
for(x=0; x<l; x++) // clear rest of the line
{
bar_buffer[idx] = 0x20;
idx--;
}
}
for(x=0; x<DISP_LEN; x++) // print buffer
{
lcdoutch(bar_buffer[x]);
}
}
/* Set LCD back light */
void set_bl(char bl)
{
#ifdef __A_TYPE
// Set up DAC
if(bl == 0)
CVREN = 0; // ref unit off
else
{
CVRCON = CVRCON_INIT | (bl - 1); // set new value
CVREN = 1; // ref unit on if it was off
}
#else
asm("nop");
#endif
}
/* General I/O functions */
void putch(unsigned char c) // put character
{
lcdoutch(c); // to LCD panel
}
void putchhex(unsigned char c) // put hex character
{
unsigned char temp;
temp=c;
c=(c >> 4);
if (c<10) c+=48; else c+=55;
putch(c);
c=temp;
c=(c & 0x0F);
if (c<10) c+=48; else c+=55;
putch(c);
}
void put1hex(unsigned char c) // put single hex digit
{
c=(c & 0x0F);
if (c<10) c+=48; else c+=55;
putch(c);
}
// writes a character to the serial port in decimal
void putchdec(unsigned char c)
{
unsigned char temp;
temp=c;
//hundreds
putch((c/100)+'0');
c-=(c/100)*100;
//tens
putch((c/10)+'0');
c-=(c/10)*10;
//ones
putch((c/1)+'0');
}
// Converts to BCD and writes out. Number must be between 0 and 99
void put2dec( char c)
{
if(c > 99)
c = 99;
//tens
putch((c/10)+'0');
c-=(c/10)*10;
//ones
putch((c/1)+'0');
}
// Converts to BCD and writes out. Number must be between -99 and +127
void put3dec( char c)
{
if(c & 0x80) // test if negative
{
c = 0 - c;
if(c > 99)
c = 99;
putch('-');
}
else
{
if ((c/100)>0)
putch((c/100)+'0');
else
putch(' ');
}
c-=(c/100)*100;
//tens
putch((c/10)+'0');
c-=(c/10)*10;
//ones
putch((c/1)+'0');
}
/*
writes int to serial port in decimal
If DP = 0 no decimal point is printed.
DP !=0 = DP place from right.
simple negative number printout added 3.7.2002
minus sign is displayed at thousands digit place
*/
void putintdec( int c, char dp)
{
int temp;
unsigned char neg_sign;
if (c > 9999) /* clip to max reading */
c = 9999;
if (c < 0) /* check if negative value */
{
neg_sign = 1;
c = 0 - c; /* invert it */
if (c > 999)
c = 999; /* max negative reading */
}
else
neg_sign = 0;
temp=c;
//thousands
if (neg_sign == 1)
putch('-');
else
{
if ((c/1000)>0 || (dp >= 3))
putch((c/1000)+'0');
else
putch(' ');
}
c-=(c/1000)*1000;
if (dp == 3)
putch('.');
//hundreds
if ( ((temp/100)>0) || ((temp/1000)>0) || (dp >= 2))
putch((c/100)+'0');
else
putch(' ');
c-=(c/100)*100;
if (dp == 2)
putch('.');
//tens
if ( ((temp/10)>0) || ((temp/100)>0) || ((temp/1000)>0) || (dp >= 1) )
putch((c/10)+'0');
else
putch(' ');
c-=(c/10)*10;
if (dp == 1)
putch('.');
//ones
putch((c/1)+'0');
}
/* write long in hex format */
void putlonghex( long ww )
{
union
{
long w;
unsigned char p[4];
} lrek;
lrek.w = ww;
putchhex(lrek.p[3]);
putchhex(lrek.p[2]);
putchhex(lrek.p[1]);
putchhex(lrek.p[0]);
}
/* put long in decimal format */
/* if mode !=0 do "short" frequency display */
void putlongdec( long x, char mode )
{
if(mode == 0) // full display
{
//giga
putch((x/1000000000)+'0');
x-=(x/1000000000)*1000000000;
putch('.');
//100_million
putch((x/100000000)+'0');
x-=(x/100000000)*100000000;
}
//10_million
if(mode !=0 && x/10000000 == 0)
putch(' '); // leadign zero blanc for frequency display
else
putch((x/10000000)+'0');
x-=(x/10000000)*10000000;
//million
putch((x/1000000)+'0');
x-=(x/1000000)*1000000;
putch('.');
//100_thousands
putch((x/100000)+'0');
x-=(x/100000)*100000;
//10_thousands
putch((x/10000)+'0');
x-=(x/10000)*10000;
//thousands
putch((x/1000)+'0');
x-=(x/1000)*1000;
putch('.');
//hundreds
putch((x/100)+'0');
x-=(x/100)*100;
//tens
putch((x/10)+'0');
x-=(x/10)*10;
//ones
putch((x/1)+'0');
}
void putst(register const char *str)
{
while((*str)!=0)
{
putch(*str);
if (*str==13) putch(10);
if (*str==10) putch(13);
str++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -