AVR单片机8位数码管显示的程序实现(两种方法介绍)

发表于 2018-01-29 10:53:17 收藏 已收藏
赞(0) •  评论(0

AVR单片机8位数码管显示的程序实现(两种方法介绍)

发表于 2018-01-29 10:53:17

本文为大家介绍两个AVR单片机8位数码管显示的程序实现。

AVR单片机595驱动8位数码管的显示的电路实现

主程序代码

#include >

#include //GCC中的延时函数头文件

#include “hc595.h”

//unsigned char Led_Disbuf[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阴极

unsigned char Led_Disbuf[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //共阳极

unsigned char ComBuf[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

//函数声明

extern void Delayus(unsigned int lus); //us延时函数

extern void Delayms(unsigned int lms); //ms延时函数

int main(void) //GCC中main文件必须为返回整形值的函数,没有参数

{

unsigned char i;

PORTB = 0xff; //PORTB输出低电平,使LED熄灭

DDRB = 0xFF; //配置端口PB全部为输出口

HC595_port_init();

while(1)

{

for(i = 0; i < 8;i++)

{

PORTB = Led_Disbuf; //送段码

HC595_Send_Data(ComBuf); //选通位选端口

Delayus(70); //延时

HC595_Send_Data(0x00); //位选通关闭

}

}

}

//us级别的延时函数

void Delayus(unsigned int lus)

{

while(lus--)

{

_delay_loop_2(4); //_delay_loop_2(1)是延时4个时钟周期,参数为4则延时16

//个时钟周期,本实验用16M晶体,则16个时钟周期为16/16=1us

}

}

//ms级别的延时函数

void Delayms(unsigned int lms)

{

while(lms--)

{

Delayus(1000); //延时1ms

}

}

AVR单片机8位数码管显示的程序实现(两种方法介绍)

模块化程序设计的.h文件

下面是本实例中模块化程序设计的.h文件

/*****************************

74hc595.h

***********************************/

/*74hc595与单片机的引脚连接

/MR(10脚) VCC 低点平时将移位寄存器的数据清零。通常将它接Vcc

/OE(13脚) PG4 高电平时禁止输出(高阻态)。

如果单片机的引脚不紧张,用一个引脚控制它,

可以方便地产生闪烁和熄灭效果。比通过数据端移位控制要省时省力。

ST_CP(12脚) PG1 上升沿时移位寄存器的数据进入数据存储寄存器,

下降沿时存储寄存器数据不变。通常将RCK置为低电平,

当移位结束后,在RCK端产生一个正脉冲(5V时,大于几十纳秒就行了。

通常都选微秒级),更新显示数据。

SH_CP(11脚) PG0 上升沿时数据寄存器的数据移位。QA-->QB-->QC-->。。。-->QH;

下降沿移位寄存器数据不变。(脉冲宽度:5V时,大于几十纳秒就行了。

通常都选微秒级)

DS(14) PG2 串行数据输入端。

*/

#ifndef __HC595_H__

#define __HC595_H__

#include //io端口寄存器配置文件,必须包含

#include //GCC中的延时函数头文件

#define HC595_latch (1 << PG1) //上升沿数据打入8位锁存器,下降沿锁存器数据不变

#define HC595_sclk (1 << PG0) //上升沿数据移位,下降沿数据不变

#define HC595_oe (1 << PG4) //低电平,8位数据锁存器输出,高电平输出高组态

#define HC595_data (1 << PG2) //串行数据输入端

#define SET_HC595_latch (PORTG |= (1 << PG1))

#define CLR_HC595_latch (PORTG &= ~(1 << PG1))

#define SET_HC595_sclk (PORTG |= (1 << PG0))

#define CLR_HC595_sclk (PORTG &= ~(1 << PG0))

#define SET_HC595_data (PORTG |= (1 << PG2))

#define CLR_HC595_data (PORTG &= ~(1 << PG2))

#define SET_HC595_oe (PORTG |= (1 << PG4))

#define CLR_HC595_oe (PORTG &= ~(1 << PG4))

void HC595_port_init(void); //595端口初始化

void HC595_Send_Data(unsigned char byte); //发送一个字节

void HC595_Output_Data(unsigned char data); //发送字符串

#endif

同时我们将与74HC595相关的函数定义部分放在74HC595.c文件中,如下

/********************************

74hc595.c

**************************************/

#include “hc595.h”

//595端口初始化

void HC595_port_init(void)

{

PORTG = 0x00;

DDRG |= (1 << PG0) | (1 << PG1) | (1 << PG2) | (1 << PG4);

}

//发送一个字节

void HC595_Send_Data(unsigned char byte)

{

unsigned char i;

//CLR_HC595_latch;

for(i = 0;i < 8;i++)

{

if(byte & 0x80)

{

SET_HC595_data;

}

else

{

CLR_HC595_data;

}

byte <<=1;

SET_HC595_sclk; //上升沿数据移位

CLR_HC595_sclk;

}

SET_HC595_latch;

CLR_HC595_latch;

}

//发送字符串

void HC595_Output_Data(unsigned char data)

{

CLR_HC595_latch; //下降沿锁存器数据不变

HC595_Send_Data(data);

SET_HC595_latch; //上升沿数据打入8位锁存器

}

AVR单片机控制8段LED数码管同时显示

这是一个简单的供单片机入门学习者练习用的8段LED数码管控制汇编程序,控制一个两位的数码管同时显示字符(动态刷新)。用AVR- Studio-4 开发,在AVR单片机Atmega48上调试通过。学习者可以举一反三应用到其他类型的单片机芯片。

arget : M48 ;

Crystal: 8.0000Mhz

.include “m48def.inc”

.org $0000 rjmp _main

.org $0020

_port_init:; 端口初始化

clr R2

out 0x5,R2 PortB清零

ldi R24,255

out 0x4,R24 定义PortB为输出

out 0x8,R2 PortC清零

ldi R24,3

out 0x7,R24 定义PortC.0,Portc.1为输出

ret

_tabs:;字形定义

.dw 192 0xC0,“0”

.dw 249 0xF9,“1”

.dw 164 0xA4,“2”

.dw 176 0xB0,“3”

.dw 153 0x99,“4”

.dw 146 0x92,“5”

.dw 130 0x82,“6”

.dw 248 0xF8,“7”

.dw 128 0x80,“8”

.dw 152 0x98,“9”

.dw 136 0x88,“A”

.dw 131 0x83,“B”

.dw 198 0xC6,“C”

.dw 161 0xA1,“D”

.dw 134 0x86,“E”

.dw 142 0x8E,“F”

.dw 255 0xFF,“8.”

_delay_1ms: 延时子程

ldi R16,1

ldi R17,0

L3:

subi R16,255 加1操作

sbci R17,255

cpi R16,232 0xE8

ldi R30,3 0x3E8 = 1000

cpc R17,R30

brlo L3 未达1000继续

ret

_delay:

push r21

push r20

push r17 入口:r16,r17装的是延时参数

push r16

movw R10,R16 将r16,r17的内容装入r10,r11

clr R20

clr R21

L8:

rcall _delay_1ms

subi R20,255 加1操作

sbci R21,255

cp R20,R10 与指定延时参数比较

cpc R21,R11

brlo L8 未达指定延时参数继续

pop r16

pop r17

pop r20

pop r21

ret

_led_display:

push R20 寄存器r20入栈,r20中带入字符表的索引

ldi R24,2

mul R24,R20 将r20中的值乘2,结果在r0中

movw R30,R0 将r0的值赋给r30,作为偏移量

ldi R24,low(_tabs<<1) 获取字符表基地址

ldi R25,high(_tabs<<1)

add R30,R24 偏移量+基地址构成z指针

adc R31,R25

lpm R20,Z+0 取字型送入r20 out 0x5,R20 字型送PortB,输出 ldi R22,0 循环100次计数寄存器r22清零

L10:

ldi R20,1 r20用于8LED数码管输出位控制,初始为1

L12:

out 0x8,R20 将8LED数码管位控制输出到端口PortC ldi R16,10 延时参数低位

ldi R17,0 延时参数高位

rcall _delay 调延时子程

inc R20 移位r20,准备显示另一位

cpi R20,3 判两位是否显示完

brlo L12 未显示完两位,继续

inc R22 r22加1

cpi R22,100 判是否已计满100 brlo L10 未计满则继续

pop R20 r20出栈 ret _main:

clr R20 初始化计数寄存器r20 rcall _port_init 初始化端口

L17:

cpi R20,16 比较循环计数

brne L21 未显示完16个字符继续

clr R20 从新开始

L21:

rcall _led_display 显示字符

inc R20 计数值加1

rjmp L17 返回

ret

收藏

相关话题
文章来源栏目
+关注

评论(0)

加载更多评论

参与评论

分享到

QQ空间 QQ好友 微博
取消