第三章 avr 通用 i/o 编程

51
第第第 第第第 AVR AVR 第第 第第 I/O I/O 第第 第第 AVR 第第 I/O 第第第 3.1 第第 I/O 第第第第 3.2 第第第第 3.3

Upload: hova

Post on 13-Jan-2016

151 views

Category:

Documents


0 download

DESCRIPTION

第三章 AVR 通用 I/O 编程. 3.1. 3.3. 3.2. AVR 通用 I/O 口结构. 编程应用. 通用 I/O 口寄存器. 三、 AVR 通用 I/O 口. 有 PORTA 、 PORTB 、 PORTC 、 PORTD (简称 PA 、 PB 、 PC 、 PD ) 4 组 8 位,共 32 路通用 I/O 接口,分别对应于芯片上 32 根 I/O 引脚。 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第三章   AVR 通用 I/O 编程

第三章 第三章 AVRAVR 通用通用 IOIO 编程编程

AVR 通用 IO 口结构31

通用 IO 口寄存器32

编程应用33

三 AVR 通用 IO口

有 PORTA PORTB PORTC PORTD(简称PA PB PC PD) 4 组 8 位共 32路通用 IO接口分别对应于芯片上 32根 IO引脚 所有这些 IO口都是双(有的为 3 )功能复用的其中第一功能均作为数字通用 IO接口使用而复用功能则分别用于中断时钟 计数器 USRAT I2C和 SPI串行通信模拟比较捕捉等应用

1 IO 口结构三 AVR 通用 IO口

结构图

1 IO 口结构三 AVR 通用 IO口

DDRx控制 IO口的输入输出方向即控制 IO口的工作方式为输出方式还是输入方式 当 DDRx=1时 IO口处于输出工作方式此时数据寄存器 PORTx中的数据通过一个推挽电路输出到外部引脚

1 IO 口结构三 AVR 通用 IO口

当 PORTx=1时 IO引脚输出高电平可提供输出 20mA的电流而当 PORTx=0时 IO引脚呈现低电平同时可吸纳 20mA电流 AVR的 IO在输出方式下提供了比较大的驱动能力可以直接驱动 LED等小功率外围器件PORTx数据输出寄存器Pin数据读入寄存器

1 IO 口结构三 AVR 通用 IO口 当 DDRx=0时 IO处于输入工作方式此时引脚寄存器 PINx中的数据就是外部引脚的实际电平通过读IO指令可将物理引脚的真实数据读入 MCU此外当IO口定义为输入时( DDRx=0)通过 PORTx的控制可使用或不使用内部的上拉电阻

1 IO 口结构三 AVR 通用 IO口

表中的 PUD为寄存器 SFIOR中的 D2位它的作用相当AVR全部 IO口内部上拉电阻的总开关当 PUD=1时 AVR所有 IO内部上拉电阻都不起作用(全局内部上拉无效)而PUD=0时各个 IO口内部上拉电阻取决于 PORTXn的设置

1 IO 口结构三 AVR 通用 IO口 Atmega通用 IO特点双向可独立位控的 IO口 ATmega16的 PA PB PC PD四个端口都是 8 位双向 IO口每一位引脚都可以单独的进行定义相互不受影响如用户可以在定义 PA口第 0 2 3 4 5 6 位用于输入的同时定义第 1 7 位用于输出互不影响1048633 Push-Pull大电流驱动 ( 最大 40mA) 每个 IO口输出方式均采用推挽式缓冲器输出提供大电流的驱动可以输出(吸入) 20mA的电流因而能直接驱动 LED显示器 1048633 可控制的引脚内部上拉电阻 当 IO口被用于输入状态且内部上拉电阻被激活(有效)时如果外部引脚被拉低则构成电流源输出电流( uA量级)DDRx可控的方向寄存器

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 2: 第三章   AVR 通用 I/O 编程

三 AVR 通用 IO口

有 PORTA PORTB PORTC PORTD(简称PA PB PC PD) 4 组 8 位共 32路通用 IO接口分别对应于芯片上 32根 IO引脚 所有这些 IO口都是双(有的为 3 )功能复用的其中第一功能均作为数字通用 IO接口使用而复用功能则分别用于中断时钟 计数器 USRAT I2C和 SPI串行通信模拟比较捕捉等应用

1 IO 口结构三 AVR 通用 IO口

结构图

1 IO 口结构三 AVR 通用 IO口

DDRx控制 IO口的输入输出方向即控制 IO口的工作方式为输出方式还是输入方式 当 DDRx=1时 IO口处于输出工作方式此时数据寄存器 PORTx中的数据通过一个推挽电路输出到外部引脚

1 IO 口结构三 AVR 通用 IO口

当 PORTx=1时 IO引脚输出高电平可提供输出 20mA的电流而当 PORTx=0时 IO引脚呈现低电平同时可吸纳 20mA电流 AVR的 IO在输出方式下提供了比较大的驱动能力可以直接驱动 LED等小功率外围器件PORTx数据输出寄存器Pin数据读入寄存器

1 IO 口结构三 AVR 通用 IO口 当 DDRx=0时 IO处于输入工作方式此时引脚寄存器 PINx中的数据就是外部引脚的实际电平通过读IO指令可将物理引脚的真实数据读入 MCU此外当IO口定义为输入时( DDRx=0)通过 PORTx的控制可使用或不使用内部的上拉电阻

1 IO 口结构三 AVR 通用 IO口

表中的 PUD为寄存器 SFIOR中的 D2位它的作用相当AVR全部 IO口内部上拉电阻的总开关当 PUD=1时 AVR所有 IO内部上拉电阻都不起作用(全局内部上拉无效)而PUD=0时各个 IO口内部上拉电阻取决于 PORTXn的设置

1 IO 口结构三 AVR 通用 IO口 Atmega通用 IO特点双向可独立位控的 IO口 ATmega16的 PA PB PC PD四个端口都是 8 位双向 IO口每一位引脚都可以单独的进行定义相互不受影响如用户可以在定义 PA口第 0 2 3 4 5 6 位用于输入的同时定义第 1 7 位用于输出互不影响1048633 Push-Pull大电流驱动 ( 最大 40mA) 每个 IO口输出方式均采用推挽式缓冲器输出提供大电流的驱动可以输出(吸入) 20mA的电流因而能直接驱动 LED显示器 1048633 可控制的引脚内部上拉电阻 当 IO口被用于输入状态且内部上拉电阻被激活(有效)时如果外部引脚被拉低则构成电流源输出电流( uA量级)DDRx可控的方向寄存器

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 3: 第三章   AVR 通用 I/O 编程

1 IO 口结构三 AVR 通用 IO口

结构图

1 IO 口结构三 AVR 通用 IO口

DDRx控制 IO口的输入输出方向即控制 IO口的工作方式为输出方式还是输入方式 当 DDRx=1时 IO口处于输出工作方式此时数据寄存器 PORTx中的数据通过一个推挽电路输出到外部引脚

1 IO 口结构三 AVR 通用 IO口

当 PORTx=1时 IO引脚输出高电平可提供输出 20mA的电流而当 PORTx=0时 IO引脚呈现低电平同时可吸纳 20mA电流 AVR的 IO在输出方式下提供了比较大的驱动能力可以直接驱动 LED等小功率外围器件PORTx数据输出寄存器Pin数据读入寄存器

1 IO 口结构三 AVR 通用 IO口 当 DDRx=0时 IO处于输入工作方式此时引脚寄存器 PINx中的数据就是外部引脚的实际电平通过读IO指令可将物理引脚的真实数据读入 MCU此外当IO口定义为输入时( DDRx=0)通过 PORTx的控制可使用或不使用内部的上拉电阻

1 IO 口结构三 AVR 通用 IO口

表中的 PUD为寄存器 SFIOR中的 D2位它的作用相当AVR全部 IO口内部上拉电阻的总开关当 PUD=1时 AVR所有 IO内部上拉电阻都不起作用(全局内部上拉无效)而PUD=0时各个 IO口内部上拉电阻取决于 PORTXn的设置

1 IO 口结构三 AVR 通用 IO口 Atmega通用 IO特点双向可独立位控的 IO口 ATmega16的 PA PB PC PD四个端口都是 8 位双向 IO口每一位引脚都可以单独的进行定义相互不受影响如用户可以在定义 PA口第 0 2 3 4 5 6 位用于输入的同时定义第 1 7 位用于输出互不影响1048633 Push-Pull大电流驱动 ( 最大 40mA) 每个 IO口输出方式均采用推挽式缓冲器输出提供大电流的驱动可以输出(吸入) 20mA的电流因而能直接驱动 LED显示器 1048633 可控制的引脚内部上拉电阻 当 IO口被用于输入状态且内部上拉电阻被激活(有效)时如果外部引脚被拉低则构成电流源输出电流( uA量级)DDRx可控的方向寄存器

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 4: 第三章   AVR 通用 I/O 编程

1 IO 口结构三 AVR 通用 IO口

DDRx控制 IO口的输入输出方向即控制 IO口的工作方式为输出方式还是输入方式 当 DDRx=1时 IO口处于输出工作方式此时数据寄存器 PORTx中的数据通过一个推挽电路输出到外部引脚

1 IO 口结构三 AVR 通用 IO口

当 PORTx=1时 IO引脚输出高电平可提供输出 20mA的电流而当 PORTx=0时 IO引脚呈现低电平同时可吸纳 20mA电流 AVR的 IO在输出方式下提供了比较大的驱动能力可以直接驱动 LED等小功率外围器件PORTx数据输出寄存器Pin数据读入寄存器

1 IO 口结构三 AVR 通用 IO口 当 DDRx=0时 IO处于输入工作方式此时引脚寄存器 PINx中的数据就是外部引脚的实际电平通过读IO指令可将物理引脚的真实数据读入 MCU此外当IO口定义为输入时( DDRx=0)通过 PORTx的控制可使用或不使用内部的上拉电阻

1 IO 口结构三 AVR 通用 IO口

表中的 PUD为寄存器 SFIOR中的 D2位它的作用相当AVR全部 IO口内部上拉电阻的总开关当 PUD=1时 AVR所有 IO内部上拉电阻都不起作用(全局内部上拉无效)而PUD=0时各个 IO口内部上拉电阻取决于 PORTXn的设置

1 IO 口结构三 AVR 通用 IO口 Atmega通用 IO特点双向可独立位控的 IO口 ATmega16的 PA PB PC PD四个端口都是 8 位双向 IO口每一位引脚都可以单独的进行定义相互不受影响如用户可以在定义 PA口第 0 2 3 4 5 6 位用于输入的同时定义第 1 7 位用于输出互不影响1048633 Push-Pull大电流驱动 ( 最大 40mA) 每个 IO口输出方式均采用推挽式缓冲器输出提供大电流的驱动可以输出(吸入) 20mA的电流因而能直接驱动 LED显示器 1048633 可控制的引脚内部上拉电阻 当 IO口被用于输入状态且内部上拉电阻被激活(有效)时如果外部引脚被拉低则构成电流源输出电流( uA量级)DDRx可控的方向寄存器

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 5: 第三章   AVR 通用 I/O 编程

1 IO 口结构三 AVR 通用 IO口

当 PORTx=1时 IO引脚输出高电平可提供输出 20mA的电流而当 PORTx=0时 IO引脚呈现低电平同时可吸纳 20mA电流 AVR的 IO在输出方式下提供了比较大的驱动能力可以直接驱动 LED等小功率外围器件PORTx数据输出寄存器Pin数据读入寄存器

1 IO 口结构三 AVR 通用 IO口 当 DDRx=0时 IO处于输入工作方式此时引脚寄存器 PINx中的数据就是外部引脚的实际电平通过读IO指令可将物理引脚的真实数据读入 MCU此外当IO口定义为输入时( DDRx=0)通过 PORTx的控制可使用或不使用内部的上拉电阻

1 IO 口结构三 AVR 通用 IO口

表中的 PUD为寄存器 SFIOR中的 D2位它的作用相当AVR全部 IO口内部上拉电阻的总开关当 PUD=1时 AVR所有 IO内部上拉电阻都不起作用(全局内部上拉无效)而PUD=0时各个 IO口内部上拉电阻取决于 PORTXn的设置

1 IO 口结构三 AVR 通用 IO口 Atmega通用 IO特点双向可独立位控的 IO口 ATmega16的 PA PB PC PD四个端口都是 8 位双向 IO口每一位引脚都可以单独的进行定义相互不受影响如用户可以在定义 PA口第 0 2 3 4 5 6 位用于输入的同时定义第 1 7 位用于输出互不影响1048633 Push-Pull大电流驱动 ( 最大 40mA) 每个 IO口输出方式均采用推挽式缓冲器输出提供大电流的驱动可以输出(吸入) 20mA的电流因而能直接驱动 LED显示器 1048633 可控制的引脚内部上拉电阻 当 IO口被用于输入状态且内部上拉电阻被激活(有效)时如果外部引脚被拉低则构成电流源输出电流( uA量级)DDRx可控的方向寄存器

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 6: 第三章   AVR 通用 I/O 编程

1 IO 口结构三 AVR 通用 IO口 当 DDRx=0时 IO处于输入工作方式此时引脚寄存器 PINx中的数据就是外部引脚的实际电平通过读IO指令可将物理引脚的真实数据读入 MCU此外当IO口定义为输入时( DDRx=0)通过 PORTx的控制可使用或不使用内部的上拉电阻

1 IO 口结构三 AVR 通用 IO口

表中的 PUD为寄存器 SFIOR中的 D2位它的作用相当AVR全部 IO口内部上拉电阻的总开关当 PUD=1时 AVR所有 IO内部上拉电阻都不起作用(全局内部上拉无效)而PUD=0时各个 IO口内部上拉电阻取决于 PORTXn的设置

1 IO 口结构三 AVR 通用 IO口 Atmega通用 IO特点双向可独立位控的 IO口 ATmega16的 PA PB PC PD四个端口都是 8 位双向 IO口每一位引脚都可以单独的进行定义相互不受影响如用户可以在定义 PA口第 0 2 3 4 5 6 位用于输入的同时定义第 1 7 位用于输出互不影响1048633 Push-Pull大电流驱动 ( 最大 40mA) 每个 IO口输出方式均采用推挽式缓冲器输出提供大电流的驱动可以输出(吸入) 20mA的电流因而能直接驱动 LED显示器 1048633 可控制的引脚内部上拉电阻 当 IO口被用于输入状态且内部上拉电阻被激活(有效)时如果外部引脚被拉低则构成电流源输出电流( uA量级)DDRx可控的方向寄存器

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 7: 第三章   AVR 通用 I/O 编程

1 IO 口结构三 AVR 通用 IO口

表中的 PUD为寄存器 SFIOR中的 D2位它的作用相当AVR全部 IO口内部上拉电阻的总开关当 PUD=1时 AVR所有 IO内部上拉电阻都不起作用(全局内部上拉无效)而PUD=0时各个 IO口内部上拉电阻取决于 PORTXn的设置

1 IO 口结构三 AVR 通用 IO口 Atmega通用 IO特点双向可独立位控的 IO口 ATmega16的 PA PB PC PD四个端口都是 8 位双向 IO口每一位引脚都可以单独的进行定义相互不受影响如用户可以在定义 PA口第 0 2 3 4 5 6 位用于输入的同时定义第 1 7 位用于输出互不影响1048633 Push-Pull大电流驱动 ( 最大 40mA) 每个 IO口输出方式均采用推挽式缓冲器输出提供大电流的驱动可以输出(吸入) 20mA的电流因而能直接驱动 LED显示器 1048633 可控制的引脚内部上拉电阻 当 IO口被用于输入状态且内部上拉电阻被激活(有效)时如果外部引脚被拉低则构成电流源输出电流( uA量级)DDRx可控的方向寄存器

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 8: 第三章   AVR 通用 I/O 编程

1 IO 口结构三 AVR 通用 IO口 Atmega通用 IO特点双向可独立位控的 IO口 ATmega16的 PA PB PC PD四个端口都是 8 位双向 IO口每一位引脚都可以单独的进行定义相互不受影响如用户可以在定义 PA口第 0 2 3 4 5 6 位用于输入的同时定义第 1 7 位用于输出互不影响1048633 Push-Pull大电流驱动 ( 最大 40mA) 每个 IO口输出方式均采用推挽式缓冲器输出提供大电流的驱动可以输出(吸入) 20mA的电流因而能直接驱动 LED显示器 1048633 可控制的引脚内部上拉电阻 当 IO口被用于输入状态且内部上拉电阻被激活(有效)时如果外部引脚被拉低则构成电流源输出电流( uA量级)DDRx可控的方向寄存器

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 9: 第三章   AVR 通用 I/O 编程

1 IO 口结构三 AVR 通用 IO口

IO口使用注意事项 1 )使用 AVR的 IO口首先要正确设置其工作方式确定其工作在输出方式还是输入方式 2 )当 IO工作在输入方式要读取外部引脚上的电平时应读取 PINxn的值而不是 PORTxn的值 3 )当 IO工作在输入方式要根据实际情况使用或不使用内部的上拉电阻如能利用 AVR内部 IO口的上拉电阻可以节省外部的上拉电阻 4 ) 一旦将 IO口的工作方式由输出设置成输入方式后必须等待一个时钟周期后才能正确的读到外部引脚 PINxn的值 5 )每次读写 IO前都要先配置 DDRx寄存器

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 10: 第三章   AVR 通用 I/O 编程

2 IO 口寄存器三 AVR 通用 IO口

每个 IO口 3 个寄存器共用 12个寄存器

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 11: 第三章   AVR 通用 I/O 编程

2 IO 口寄存器三 AVR 通用 IO口

下图是 PA口寄存器mdash PORTA DDRA PINA各个位的具体定义及复位初始值其它 3 个口的寄存器的情况与PA口相同只是地址不一样

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 12: 第三章   AVR 通用 I/O 编程

3 IO 口编程应用三 AVR 通用 IO口

一种标准的 C 程序可以采用以下的写法 define BIT0 0 helliphellip define BIT7 7 PORTC = 1ltlt(BIT0) | 1ltlt(BIT3) PC口的第 0 位和第 3 位输出ldquo 1rdquo其它为ldquo 0rdquo1ltlt(BIT0) 表示逻辑 1 左移 0 位结果为 0b000000011ltlt(BIT3) 表示逻辑 1 左移 3 位结果为 0b000010000b00000001 在同 0b00001000 相或结果为 0b00001001 以上的逻辑运算不产生具体的操作指令由编译器在编译时运算完成得到结果最后只是产生将结果赋值到PORTC寄存器的操作指令 这种表示方法有利于ldquo不同 CPU的移植rdquo

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 13: 第三章   AVR 通用 I/O 编程

3 IO 口编程应用三 AVR 通用 IO口

这种表示方式比直接赋值 0b00001001更容易理解程序的作用在后面的程序将广泛使用这种表达方法如对USART串口编程中大量使用了这样的描述方式

define RXB8 1 define TXB8 0 define UPE 2 define OVR 3 define FE 4 define UDRE 5 define RXC 7 define FRAMING_ERROR (1ltltFE) define PARITY_ERROR (1ltltUPE) define DATA_OVERRUN (1ltltOVR)

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 14: 第三章   AVR 通用 I/O 编程

3 IO 口编程应用三 AVR 通用 IO口

define DATA_REGISTER_EMPTY (1ltltUDRE) define RX_COMPLETE (1ltltRXC) helliphelliphellip char status status = UCSRA if (( status amp ( FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN )) == 0 ) helliphellip 接收数据无错误处理过程 else helliphellip 接收数据产生错误处理过程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 15: 第三章   AVR 通用 I/O 编程

3 IO 口编程应用三 AVR 通用 IO口

程序中的 UCSRA为 ATmega16的串行接口 USART的状态寄存器 UPE是 UCSRA的第 2 位当 UPE为 1 时表示接收到的数据产生了校验错误 程序中采用了定义语句定义 PARITY_ERROR为( 1 ltlt UPE) 实际就是 0b00000100 因此一旦 USART的值为 PARITY_ERROR时 表示接受的数据产生了校验错误使程序的阅读非常明了

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 16: 第三章   AVR 通用 I/O 编程

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 17: 第三章   AVR 通用 I/O 编程

( 1 ) LED 发光二极管驱动三 AVR 通用 IO口

include ltiom16vhgtvoid delay(unsigned char t) 声明函数 void main(void) char position = 0 positionIcircordfiquestOslashOumlAEligIcircraquomicroAumlIcircraquoOumlAtilde PORTA=0xFF PAiquestUacuteEcircaumlsup3oumlEgravelaquo1poundnotLEDEgravelaquoAtildeeth DDRA=0xFF PAiquestUacutesup1currentimesdivideIcircordfEcircaumlsup3oumlmiddotfrac12Ecircfrac12 while (1) PORTA = ~(1ltltposition) timesoacuteOgraveAEligOgraveraquoIcircraquo if (++position gt= 8) position = 0 delay(100) 定义函数 void delay(unsigned char t) unsigned char ab for(a=0alt100a++) for(b=0blttb++)

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 18: 第三章   AVR 通用 I/O 编程

( 2 )继电器控制三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 19: 第三章   AVR 通用 I/O 编程

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 20: 第三章   AVR 通用 I/O 编程

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 21: 第三章   AVR 通用 I/O 编程

( 3 )步进电机驱动三 AVR 通用 IO口

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 22: 第三章   AVR 通用 I/O 编程

( 3 )步进电机驱动三 AVR 通用 IO口

单极 3 相步进电机有三个磁激励相分别用A B C 表示每相有一个磁激线圈通过控制三个磁激线圈电流的通断的先后时间顺序和通断频率就可以改变步进电机的变旋转方向和控制转速图 6-9是单极 3 相步进电机的原理图 单极 3 相步进电机有 3 相 3 拍和 3 相 6 拍两种驱动方式图 6-10给出它们的控制时序图 3 相 3 拍就是A B C 三相分别通电正转为 A - B - C - A - B- C 反转为 A - C - B - A - C - B 每拍转动3deg 3 相 6 拍中有三拍是两相同时通电正转为 A - AB- B - BC- C - CA反转为 A - AC- C - CB- B -BA每拍转动 15deg

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 23: 第三章   AVR 通用 I/O 编程

( 3 )步进电机驱动三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char step_out[6]=0x040x060x020x030x010x05 void main(void) char i = 0 int delay = 500 PORTA=0x00 DDRA=0x07 while (1) PORTA = step_out[i] if (++i gt= 6) i = 0 delay_ms(delay)

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 24: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 25: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(并行)三 AVR 通用 IO口

假设 PA0-ahellipPA7-h要显示数字lsquo 1rsquo共阴极 PA输出共阳级 PA输出与此同时公共端接法欲连续显示数字 0-9该如何

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 26: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 27: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(并行)三 AVR 通用 IO口

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 28: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(并行)三 AVR 通用 IO口

include ltmega16hgt include ltdelayhgt flash char led_7[10]=0x3F0x060x5B0x4F0x660x6D0x7D0x070x7F0x6F flash char position[6]=0xfe0xfd0xfb0xf70xef0xdf char time[3] 时分秒计数 char dis_buff[6] 显示缓冲区存放要显示的 6 个字符的段码值 char time_counter 1 秒计数器 全局变量bit point_on 秒显示标志 全局变量

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 29: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(并行)三 AVR 通用 IO口

void display(void) 扫描显示函数执行时间 12ms char i for(i=0ilt=5i++) PORTA = led_7[dis_buff[i]] if (point_on ampamp ( i==2 || i==4 )) PORTA |= 0x80 (1) PORTC = position[i] delay_ms(2) (2) PORTC = 0xff (3)

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 30: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(并行)三 AVR 通用 IO口

void time_to_disbuffer(void) 时间值送显示缓冲区函数 char ij=0 for (i=0ilt=2i++) dis_buff[j++] = time[i] 10 dis_buff[j++] = time[i] 10 void main(void) DDRA=0xFF PA 全部置为输出PORTA=0x00 PORTA 初始化 DDRC=0x3F PC 的低 6 位置为输出其他为输入PORTC=0x3F PORTC 初始化

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 31: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(并行)三 AVR 通用 IO口

time[2] = 23 time[1] = 58 time[0] = 55 时间初值time_to_disbuffer() while (1) display() 显示扫描执行时间 12ms If (++time_counter gt= 40) time_counter = 0 ( 4 ) point_on = ~point_on ( 5 ) if (++time[0] gt= 60) time[0] = 0 if (++time[1] gt= 60) time[1] = 0 if (++time[2] gt= 24) time[2] = 0 time_to_disbuffer() delay_ms(13) 延时 13ms 可进行其它处理( 6 )

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 32: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 33: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(串行)三 AVR 通用 IO口

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 34: 第三章   AVR 通用 I/O 编程

( 3 )数码管显示(串行)三 AVR 通用 IO口

define HC164_data PORTA0 define HC164_clk PORTA1 void HC164_send_byte(char byte) char i for (i=0ilt=7i++) HC164_data = byte amp 1ltlt i HC164_clk = 1 HC164_clk = 0 void display(void) char tempi for(i=0ilt=5i++) temp = led_7[dis_buff[i]] if (point_on ampamp (i==2 || i==4)) HC164_send_byte(temp | 0x80)

else HC164_send_byte(temp) PORTC = position[i] delay_ms(2) PORTC = 0xff

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 35: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 36: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 37: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 38: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

指令 1 清显示光标复位到地址 00H 位置指令 2 光标复位光标返回到地址 00H 指令 3 光标和显示模式设置 ID 光标移动方向高电平右移低电平左移 S 屏幕上所有文字是否左移或者右移高电平表示有效低电平则无效

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 39: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

指令 4 显示开关控制 D 控制整体显示的开与关高电平表示开显示低电平表示关显示 C 控制光标的开与关高电平表示有光标低电平表示无光标 B 控制光标是否闪烁高电平闪烁低电平不闪烁指令 5 光标或显示移位 SC 高电平时移动显示的文字低电平时移动光标 RL 高向左低向右指令 6 功能设置命令 DL 高电平时为 4 位总线低电平时为 8 位总线 N 低电平时为单行显示高电平时双行显示 F 低电平时显示 5x7 的点阵字符高电平时显示 5x10 的点阵字符(有些模块是 DL 高电平时为8 位总线低电平时为 4 位总线)

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 40: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

指令 7 字符发生器 RAM 地址设置地址字符地址 8+ 字符列数列数0-15

指令 8 置显示地址第 0 行为 80Hmdashmdash8FH 第 1 行为 C0HmdashmdashCFH 数 0-1 指令 9 读忙信号和光标地址 BF 为忙标志位高电平表示忙此时模块不能接收命令或者数据如果为低电平表示不忙指令 10 写数据指令 11 读数据

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 41: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

编程分成应用程序和驱动程序两部分

驱动程序 写命令 初始化清零设置光标是否移位等操作 写数据 显示一个字符显示一串字符串

应用程序 直接调用驱动程序的相关函数完成对 LCD的初始化和数据显示

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 42: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

函数功能简介1 ) void LCD_init(void)该函数对 LCD 进行初始化将显示位置回到第 0 行的第 0 列的起始位置处函数的参数应是 LCD 显示器的列数(一行能够显示的字符数)使用 LCD 显示器时必须先使用该函数对 LCD 显示器进行初始化 2 ) void LCD_clear(void) 该函数清除 LCD 的显示并将显示位置回到第 0 行的第 0 列的起始位置处 3 ) void LCD_write_data(unsigned char data) 写数据到 LCD 4 ) LCD_write_char(unsigned char xunsigned char yunsigned char data) 在指定位置显示单个字符 5 ) void LCD_write_str(unsigned char xunsigned char yunsigned char s) 该函数将在从当前的显示位置开始显示连续字符串( str 为 SRAM 中定义的字符串的指针)

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 43: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

6 ) void LCD_write_com(unsigned char com) 写命令到 LCD

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 44: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

Lcd_driverh 程序内容include ltiom16vhgtdefine RS_CLR PORTD amp= ~(1 ltlt PD3)define RS_SET PORTD |= (1 ltlt PD3)define RW_CLR PORTD amp= ~(1 ltlt PD4)define RW_SET PORTD |= (1 ltlt PD4)define EN_CLR PORTD amp= ~(1 ltlt PD6)define EN_SET PORTD |= (1 ltlt PD6)define DATA_PORT PORTB

void delay_us(unsigned int n) if (n == 0) return while (--n)

void delay_ms(unsigned char i) unsigned char a b for (a = 1 a lt i a++) for (b = 1 b b++)

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 45: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

写命令函数 void LCD_write_com(unsigned char com) RS_CLR RW_CLR EN_SET DATA_PORT = com delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 46: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

显示数据 void LCD_write_data(unsigned char data) RS_SET RW_CLR EN_SET PORTB = data delay_us(5) EN_CLR

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 47: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

显示字符串 void LCD_write_str(unsigned char xunsigned char yunsigned char s) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xc0 + x) while (s) LCD_write_data( s) s ++

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 48: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏单字符写入函数 void LCD_write_char(unsigned char xunsigned char yunsigned char data) if (y == 0) LCD_write_com(0x80 + x) else LCD_write_com(0xC0 + x) LCD_write_data( data)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 49: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏清空显示 void LCD_clear(void) LCD_write_com(0x01) delay_ms(5)

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 50: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

显示屏初始化函数 void LCD_init(void) LCD_write_com(0x3c) 显示模式设置 0011 1000 delay_ms(5) LCD_write_com(0x08) 显示关闭 0000 1000 LCD_write_com(0x01) 显示清屏 0000 0001 LCD_write_com(0x06) 显示光标移动设置 0000 01100 delay_ms(5) LCD_write_com(0x0C) 显示开及光标设置 0000 1100

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)

Page 51: 第三章   AVR 通用 I/O 编程

( 4 )字符 LCD

三 AVR 通用 IO口

初始化及主程序include ltiom16vhgtinclude ldquolcd_driverhvoid main(void) unsigned char i unsigned char p delay_ms(100) LCD_init()

while (1) i = 1 p = ldquoWelcom to G403rdquo LCD_clear() LCD_write_str(50ldquoHello LCD) delay_ms(250) while (p) LCD_write_char(i1p) i ++ p ++ delay_ms(250) delay_ms(250)