关于北航AVR那本书里LCD显示程序里lcd_putchar()的疑问
关于书本P197 lcd_putchar(0), lcd_putchar(1), lcd_putchar(2)用法的疑问,希望一些碰到过类似问题的朋友略作解答,谢谢了。我查到的相关资料如下:
void lcd_putchar(char c) //将字符c在当前的显示位置上显示出来
google, baidu后发现也有用ASCII码值来代替char c的用法,这些还是理解的。
从LCD.LIB里找出了该函数的出处,如下:
#pragma keep+
void lcd_putchar(char c)
{
#asm
push r30
push r31
ld r26,y
set
cpir26,10
breq __lcd_putchar1
clt
#endasm
++_lcd_x;
if (_lcd_x>_lcd_maxx)
{
#asm("__lcd_putchar1:")
++_lcd_y;
lcd_gotoxy(0,_lcd_y);
#asm("brts __lcd_putchar0")
};
#asm
rcall __lcd_ready
sbi__lcd_port,__lcd_rs ;RS=1
ld r26,y
st -y,r26
rcall __lcd_write_data
__lcd_putchar0:
popr31
popr30
#endasm
}
#pragma keep-
我了解到的东西也就这些,自己推断了一下,lcd_putchar(0), lcd_putchar(1), lcd_putchar(2)中的0, 1, 2应该就是ASCII码了,分别为NULL, SOH(start of heading), STX(start of text)的意思,没法理解,感觉0, 1, 2像是字符串的首地址。书是第一次印刷的,但我已核对了到09年为止所有4个勘误表,感觉不是勘误的问题,也对站里的帖子进行了搜索,还是不行,特来请教。 源程序如下,疑问在倒数3,4,5行。
/*********************************************
File name : Demo_6_9.c
Chip type : ATmega16
Program type : Application
Clock frequency : 4.000000 MHz
Memory model : Small
External SRAM size: 0
Data Stack size : 256
*********************************************/
#include <mega16.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x15
#endasm
#include <lcd.h>
typedef unsigned char byte;
/* table for the user defined character */
flash byte char0={ // 天的字型
0b0011111,
0b0000100,
0b0000100,
0b0011111,
0b0000100,
0b0000100,
0b0001010,
0b0010001};
flash byte char1={ // 向的字型
0b0000100,
0b0001000,
0b0011111,
0b0010001,
0b0011111,
0b0011011,
0b0011111,
0b0010001};
flash byte char2={ // 上的字型
0b0000100,
0b0000100,
0b0000111,
0b0000100,
0b0000100,
0b0000100,
0b0000100,
0b0011111};
/* function used to define user characters */
void define_char(byte flash *pc,byte char_code)
{
byte i,a;
a=(char_code<<3) | 0x40;
for (i=0; i<8; i++) lcd_write_byte(a++,*pc++);
}
void main(void)
{
lcd_init(16); // initialize the LCD for 2 lines & 16 columns
define_char(char0,0);// define user character 0
define_char(char1,1);// define user character 1
define_char(char2,2);// define user character 2
lcd_clear();
lcd_putsf("Demo_6_9.c"); // 第一行显示内容
lcd_gotoxy(0,1);
lcd_putsf("User define:"); // 第二行显示内容
lcd_putchar(0); // 接在后面显示"天天向上"
lcd_putchar(0);
lcd_putchar(1);
lcd_putchar(2);
while (1);
} 先提供你必须参考的资料:
1。HD44780的器件手册(书的光盘中有中文的一般介绍,网上可以找到详细的资料),了解该器件的基本功能和内部结构。
2。CVAVR的HELP中关于LCD的函数说明。
下面贴出我书中代码的出处(来自CVAVR的HELP,仅与上面代码相关部分):
LCD Functions
..................
void lcd_write_byte(unsigned char addr, unsigned char data);
writes a byte to the LCD character generator or display RAM.
Example:
/* LCD user defined characters
Chip: AT90S8515
Memory Model: SMALL
Data Stack Size: 128 bytes
Use an 2x16 alphanumeric LCD connected
to the STK200+ PORTC header as follows:
1 GND- 9GND
2 +5V- 10 VCC
3 VLC- LCD HEADER Vo
4 RS - 1PC0
5 RD - 2PC1
6 EN - 3PC2
11 D4 - 5PC4
12 D5 - 6PC5
13 D6 - 7PC6
14 D7 - 8PC7 */
/* the LCD is connected to PORTC outputs */
#asm
.equ __lcd_port=0x15 ;PORTC
#endasm
/* include the LCD driver routines */
#include <lcd.h>
typedef unsigned char byte;
/* table for the user defined character
arrow that points to the top right corner */
flash byte char0={
0b0000000,
0b0001111,
0b0000011,
0b0000101,
0b0001001,
0b0010000,
0b0100000,
0b1000000};
/* function used to define user characters */
void define_char(byte flash *pc,byte char_code)
{
byte i,a;
a=(char_code<<3) | 0x40;
for (i=0; i<8; i++) lcd_write_byte(a++,*pc++);
}
void main(void)
{
/* initialize the LCD for 2 lines & 16 columns */
lcd_init(16);
/* define user character 0 */
define_char(char0,0);
/* switch to writing in Display RAM */
lcd_gotoxy(0,0);
lcd_putsf("User char 0:");
/* display used defined char 0 */
lcd_putchar(0);
while (1); /* loop forever */
}
..................
void lcd_putchar(char c)
displays the character c at the current display position.
=================================================================================================
首先要理解,LCD上显示一个字符“0”是如何实现的?
1。LCD要显示字符,也是一行一行的输出这个字符的点阵(字模)
2。在HD44780中已经固化有“0”的字摸,当然也有其他字符的字模,包括所有的标准ASCII字符(<0X7F)以及非标的字符(>0x80)(见HD44780的内部字符集)。这些字模实际是在HD44780的CGROM中,每个占8个字节,每个字节是一行的点阵(实际高3位不用,因为HD44780的字符集固定使用5*7点阵,第8行是光标)
3。HD44780中有64个字节的CGRAM,提供用户自己定义最多8个字符的点阵,放在里面供显示使用。当然掉电就没有了,需要上电后在写入的。
4。void lcd_putchar(char c)不是标准C的函数,是CVAVR系统内部提供的,专门的LCD函数,主要针对使用HD44780做驱动的通用LCD模块的操作函数。
------------------------------------------------
如果你仔细看了资料,并明白上面的基本知识,我们就可以分析这段代码是什么意思了。
首先看void lcd_putchar(char c)这个函数,在CVAVR的HELP中的解释是“displays the character c at the current display position.”,这个解释没有问题,关键是你的理解。
char C:是字符,可能 lcd_putchar(“0”);你能理解:是显示字符“0”,那么具体如何操作呢?当然是找到字符“0”对应的点阵8个字节,把它们一行行送到屏幕对应的DDRAM中。
那么lcd_putchar(0x30);你能理解吗?0x30就是“0”的ASCII代码,实际与lcd_putchar(“0”);是一个意思。lcd_putchar(“0”)就是lcd_putchar(0x30),这里0x30实际就是一个数组的首地址(“0”字符点阵的首地址)。因此你的理解是对的,lcd_putchar(char c)中的char c ,实际是把ASCII码值做为首地址,到对应的点阵数组中取显示点阵。
(再具体点:lcd_putchar(0x30)是将0x30左移3位后得到一个首地址,然后从该地址处连续取8个字节的点阵送屏幕显示的相应内存中)
那么lcd_putchar(0)呢?0当然是个首地址了,根据ASCII表,0X00是字符“NULL”,不错的。但由于ASCII字符0X00-0x07用的比较少,在HD44780中,把这8个字符定义到用户64个CGRAM中了,这里面可以由用户定义这8个字符的特殊的“显示”样子。
在我例子中,你可以这样理解:
lcd_putchar(0)是在当前位置显示字符“NULL”,而“NULL”的显示样子为中文“天”,该样子是用define_char(char0,0)填入定义的。
void lcd_putchar(char c)没有错,lcd_putchar(0)也是正确的。关键是你没有仔细看HD44780的手册。下面提供最原始的手册,有兴趣看吗?
点击此处下载 ourdev_471390.pdf(文件大小:292K) (原文件名:HD44780.pdf) HD44780器件手册.pdf
CodeVisionAVR C Compiler Help中的LCD Functions, LCD Functions for displays connected in 8 bit memory mapped mode, LCD Functions for displays with 4x40 characters
HD44780.pdf
刚把以上资料都看了一遍,谢谢马老师细心的解答,学到不少,以后提问之前我会去仔细研究一下相关硬件的datasheet和软件的help文档。
下面附一张解答中有关CGRAM的图:
http://cache.amobbs.com/bbs_upload782111/files_17/ourdev_471451.jpg
CGRAM (原文件名:CGRAM.jpg) lcd_putchar(0)- lcd_putchar(7)是到CGRAM中取用户定义的字符点阵数据
lcd_putchar(8)以上就到CGROM中取内部固化好的,标准ASCII码字符的点阵数据
void lcd_putchar(char C)函数里面就转了这么个小小的圈子,使得方便的配合HD44780工作的。
页:
[1]