搜索
bottom↓
回复: 4

关于北航AVR那本书里LCD显示程序里lcd_putchar()的疑问

[复制链接]

出0入0汤圆

发表于 2009-8-15 20:09:50 | 显示全部楼层 |阅读模式
关于书本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
    cpi  r26,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:
    pop  r31
    pop  r30
#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个勘误表,感觉不是勘误的问题,也对站里的帖子进行了搜索,还是不行,特来请教。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2009-8-15 21:16:09 | 显示全部楼层
源程序如下,疑问在倒数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[8]={                // 天的字型
0b0011111,
0b0000100,
0b0000100,
0b0011111,
0b0000100,
0b0000100,
0b0001010,
0b0010001};
flash byte char1[8]={                // 向的字型
0b0000100,
0b0001000,
0b0011111,
0b0010001,
0b0011111,
0b0011011,
0b0011111,
0b0010001};
flash byte char2[8]={                // 上的字型
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);
}

出0入0汤圆

发表于 2009-8-16 03:30:06 | 显示全部楼层
先提供你必须参考的资料:

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:

   [LCD]   [STK200+ PORTC HEADER]
    1 GND- 9  GND
    2 +5V- 10 VCC  
    3 VLC- LCD HEADER Vo
    4 RS - 1  PC0
    5 RD - 2  PC1

    6 EN - 3  PC2
   11 D4 - 5  PC4
   12 D5 - 6  PC5
   13 D6 - 7  PC6
   14 D7 - 8  PC7 */

/* 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[8]={
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[1].pdf)

出0入0汤圆

 楼主| 发表于 2009-8-16 13:26:14 | 显示全部楼层
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[1].pdf

刚把以上资料都看了一遍,谢谢马老师细心的解答,学到不少,以后提问之前我会去仔细研究一下相关硬件的datasheet和软件的help文档。
下面附一张解答中有关CGRAM的图:


CGRAM (原文件名:CGRAM.jpg)

出0入0汤圆

发表于 2009-8-16 14:04:12 | 显示全部楼层
lcd_putchar(0)- lcd_putchar(7)是到CGRAM中取用户定义的字符点阵数据
lcd_putchar(8)以上就到CGROM中取内部固化好的,标准ASCII码字符的点阵数据

void lcd_putchar(char C)函数里面就转了这么个小小的圈子,使得方便的配合HD44780工作的。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-15 14:59

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表