历史上的今天
今天是:2025年01月06日(星期一)
2020年01月06日 | AVR单片机8位数码管显示的程序实现
2020-01-06 来源:eefocus
我们接着来完成 数码管的显示实验。现在我们开始动手编写程序;
根据前面的介绍,我们应该已经能够知道编写一个 的C语言程序的基本步骤和方法了。
下面给出这个程序的主程序文件,在这个程序中我们应该能够知道这个程序都包含了那几块,具体来说我们应该能够在这个程序中把以下几个部分找出来:预编译语句、 的定义、函数的声明、主函数、函数定义。如果你还不能够准确找出这几部分,那么需要把前面的内容再详细阅读一下。
主程序代码
#include < /io.h> //io端口寄存器配置文件,必须包含
#include #include "hc .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输出低电平,使 熄灭 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 } } 在这个主程序文件中有人可能会注意到有一些我们前面没有介绍过的内容,比如extern这个单词,它在这里起什么作用? 这就牵涉到C语言的关键字了,关于C语言的关键字,我们可以到相关的C语言教材中去做详细了解,在这里我们只针对extern这个关键字作出解释,我们注意到extern用在一个函数声明的地方,它的作用就是把这个函数声明为外部函数,这样我们在整个项目的所有文件中就都可以调用这个函数了。同理extern也可以用来声明一个变量为外部变量。 我们可能还会有一个疑惑:#include "hc595.h"这个头文件包含语句中的hc595.h有什么作用,它是GCC提供的还是我们自己编写的? 这里我们就要学习C语言中的一个重要的概念:模块化程序设计。何为模块化程序设计?它实现什么功能?如果要铺开来讲的话,可能需要一本书的内容。我们耗不起这个时间和精力。其实我们只需要知道,模块化程序设计是为了简化程序容量而采取的一种将一个程序分成不同的模块,然后通过特定的方法将这些模块组合起来共同完成同一个目标。通俗的说就是化整为零。 在我们刚开始学习 的时候,我们编写的程序都很简单,程序量也不大,所以往往涉及不到模块化程序设计,但是这是一种很好的编程思路,我们有必要掌握。本实例就是采用的这种方法。 模块化程序设计的思路是:将实现相同功能的程序单独编写,然后实现一个综合的功能,举个例子,我们想实现一个液晶显示的温度测量程序,那么我们可以把液晶显示相关的程序放在一个文件中,把温度测量的程序放在另一个文件中,最后在主程序中调用这两个文件来实现整体的功能。 通常我们在进行模块化程序设计的时候,常常将 ,端口设置,函数声明等部分保存在一个.h文件中,而将函数定义部分放在一个.c文件中,在编写主程序文件的时候,用预处理命令#include将.h文件包含起来,而在编译的时候将所有用到的.c文件一起编译。这样就实现了模块化文件的整合。 在本实例中,我们将74HC595相关的变量定义,端口定义,函数声明放在74HC595.h文件中,而主程序中的#include "hc595.h"这句话实现了将这个文件包含到主程序中的功能。 下面是本实例中模块化程序设计的.h文件 /***************************** .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 #include #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位锁存器 } 在主程序中我们使用预定义语句将.h文件包含到了主程序文件中,那么我们怎样实现将.c文件编译到整个项目程序中呢?在这里我们只要在makefile文件中将这个.c文件加进去就可以了,如下图所示,在SRC = $(TARGET).C的后面空一格,然后输入我们所定义的.c文件的名称,然后保存makefile文件的更改。最后进行编译就可以了,编译的时候如果我们仔细观察编译器的输出信息,会发现不但编译了main.c文件,同时也编译了74hc595.c文件。
史海拾趣
|
作者:崔晓楠 日期:2006-11-1 来自 今日电子 美国华盛顿州立大学物理系研究人员近日设计出一种新型分子,其对光的传播的控制能力比现有的最好材料提高了近20倍,一旦成功用于超快光电开关,将能大大提高互联网与光通信的速度。 研究 ...… 查看全部问答> |
|
用串行总线(USB)原理及接口设计 摘要:以USB1.1为基础讨论了USB的基本原理、工作流程、通信协议和相应的关键技术,并介绍了一种USB接口的10M以太网卡的设计方案。已经发布的USB2.0支持480Mbps的高速数据传输,这将使P ...… 查看全部问答> |
|
问题是这样,我用videnc_copy修改,加入我的放大算法代码,在process里面要用到width height pitch等值, 要传参数,我把这些变量放到process里面声明称局部变量并赋初值,程序就跑的很快(20ms),但是我把这几个变量 复制到process的外面(全局 ...… 查看全部问答> |
|
探讨一下关于symbian智能手机操作系统的技术问题 各位从事symbian 智能手机研发或者从事相关电信领域工作的同弟姐妹们,我从事这方面的工作有相当长 的时间,对这个行业,包括有些技术领域有些困惑,想结识一些有同样背景的朋友们,做一下各方 ...… 查看全部问答> |
|
大家做的产品,无论是量产的还是正在开发中的,都打上了CE5的补丁了吗?这些补丁全部打上之后对系统的性能会有改善或者倒退的影响吗? 我现在正在做的产品没有打任何补丁,但是总感觉电源管理有些问题,有时候睡眠唤醒收不到PBT_TRANSITION以及PBT ...… 查看全部问答> |
|
正在使用FPGA- XINLINX 请教如果设置大量的寄存器 请教各位高手和版主: 如何使用RAM设置大量的寄存器?(仅仅听说这种方法,不知道是不是这样称呼)。 如果使用状态机特别的麻烦,每设置一个寄存器要使用4个状态,1k就要有4000个状态,实在是太麻烦了,请教有什么简便的方法么?谢谢了····· [ ...… 查看全部问答> |
|
一、环境说明:HALCoGen :版本03.05.02CCS :版本Code Composer Studio Version:5.4.0.00091硬件 :TMS570LS031USB 二、工作目录: CCS工作 ...… 查看全部问答> |
|
1. 设计要求单臂式雨刮器,步进电机驱动,摆角+70o, 周期范围为0.5S~20S。需根据雨量传感器数据调整摆动周期。需要使用显示器显示当前雨刮器的摆动周期。雨刮器说明:为防损坏雨刮,雨刮器每步摆动角必需小于1o ,请根据这个需要选择步距角合适的步 ...… 查看全部问答> |




