蓝桥杯嵌入式国赛模块训练之数码管
Posted 丿晓龙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯嵌入式国赛模块训练之数码管相关的知识,希望对你有一定的参考价值。
前言
数码管是蓝桥杯嵌入式国赛需准备的第一个模块,然而在国赛中数码管的驱动官方是不会给的,需要我们自己编写,乍一看似乎有点繁琐,但是稍微看一会之后就会发现其实没什么难度,能看懂电路图,搞清楚SN74LS595N这个“八位输出锁存移位寄存器”的工作原理之后一切就迎刃而解了。
一、电路原理图
1.共阴极数码管
上图就是扩展板上的电路原理图,扩展板上一共有三个数码管,他们都属于共阴极数码管。数码管的输入端为a、b、c、d、e、f、g和DP,其中DP为小数点的控制端。所谓共阴极就是指输入高电平时相应的位置亮,共阳极与之相反。下图为数码管输入端对应位置:
由此可以推出数码管不同的输入对应显示的形状:
数字0应该是A、B、C、D、E、F亮,对应输入00111111,十六进制为0x3f
数字1应该是B、C亮,对应输入00000110,十六进制为0x06
同理:
数字2对应十六进制0x5b
数字3对应十六进制0x4f
数字4对应十六进制0x66
数字5对应十六进制0x6d
数字6对应十六进制0x7d
数字7对应十六进制0x07
数字8对应十六进制0x7f
数字9对应十六进制0x6f
有些题目要求我们显示十六进制,所以还要显示A、b、C、d、E、F来表示某些十六进制数
A对应十六进制0x77
b对应十六进制0x7c
C对应十六进制0x39
d对应十六进制0x5e
E对应十六进制0x79
F对应十六进制0x71
数码管全灭对应十六进制为0x00
PS.以上全是不带小数点对应的十六进制数,若要显示小数点只需把DP对应的那一位置1即可。
2.SN74LS595N
SN74LS595N为八位输出锁存移位寄存器,控制端~OE 、 ~SRCLR电路已经接好我们不需要关系,我们只需要控制RCLK、SCK、和SER这个三个端口就可以了。
管脚说明:
1.SCK:上升沿时数据寄存器的数据移位,下降沿移位寄存器数据不变。即只有在SCK上升沿的时候把移位寄存器中的数据移动一位,此时SER的电平被移进移位寄存器的最低位。
2.RCK:上升沿时移位寄存器的数据进入数据存储寄存器,下降沿时存储寄存器数据不变。
3.SER:每输入一位数据,串行输入时钟 SCK 上升沿有效一次,直到八位数据输入完毕。
因此我们要想显示一个数字,首先需要把该数字对应的二进制一位一位的移进移位寄存器,也就是SER输出一次然后再让SCK产生一次上升沿,最后在所有位移动完成后让RCK产生一次上升沿,使移位寄存器中的数据进入数据寄存器,然后SN74LS595N就能输出我们先要的电平,使数码管显示想要显示的数字。
3. 扩展板跳线帽连接
这里给出官方的配置表:
由图可以看出,要想使用数码管,我们必须按照如图所示连接跳线帽:
P4.1(PA1)要连接P3.1(SER),P4.2(PA2)要连接P3.2(RCK),P4.3(PA3)要连接P3.3(SCK)。下图为实物连接:
二、驱动代码
1.seg.h
代码如下:
#ifndef __SEG_H
#define __SEG_H
#include "stm32f10x.h"
#define RCLK_H GPIO_SetBits(GPIOA,GPIO_Pin_2)
#define RCLK_L GPIO_ResetBits(GPIOA,GPIO_Pin_2)
#define SCK_H GPIO_SetBits(GPIOA,GPIO_Pin_3)
#define SCK_L GPIO_ResetBits(GPIOA,GPIO_Pin_3)
#define SER_H GPIO_SetBits(GPIOA,GPIO_Pin_1)
#define SER_L GPIO_ResetBits(GPIOA,GPIO_Pin_1)
void SEG_Init(void);
void SEG_ShowN(u8 n1,u8 n2,u8 n3);
#endif
头文件中define了三个控制端的拉高和拉低,定义了SEQ_Init(void)用来初始化三个GPIO口,SEG_ShowN(u8 n1,u8 n2,u8 n3)用来让三个数码管显示数字。
2.seg.c
代码如下:
#include "seg.h"
u8 SEG[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
void SEG_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void SEG_ShowN(u8 n1,u8 n2,u8 n3)
{
u8 i = 0;
u8 code_tmp = 0;
code_tmp = SEG[n3];
for(i = 0;i<8;i++)
{
if(code_tmp&0x80) SER_H;
else SER_L;
SCK_H;
code_tmp <<= 1;
SCK_L;
}
code_tmp = SEG[n2];
for(i = 0;i<8;i++)
{
if(code_tmp&0x80) SER_H;
else SER_L;
SCK_H;
code_tmp <<= 1;
SCK_L;
}
code_tmp = SEG[n1];
for(i = 0;i<8;i++)
{
if(code_tmp&0x80) SER_H;
else SER_L;
SCK_H;
code_tmp <<= 1;
SCK_L;
}
RCLK_H;
RCLK_L;
}
c文件中首先定义了一个数组,里面是按照0,1,2,3…的顺序存放的八位数据。
然后再说void SEG_ShowN(u8 n1,u8 n2,u8 n3)这个函数:
在这个函数中,首先定义了一个变量,从SEG[17]数组中取值,然后进入一个循环,每一次判断code_tmp 的最高位是0还是1,同时使SER输出低或者高电平。然后使SCK产生一次上升沿,使得移位寄存器移位一次,此时SER的输入就移进了移位寄存器的最低位,并且在每次循环的最后让code_tmp <<1,所以循环八次之后这个八位数据就全部移进了移位寄存器中,然后再经过两次这样的操作。三个SN74LS595N的移位寄存器中就存放了相应的数据,所以最后再让RCK产生一次上升沿,就把数据存放到了数据寄存器中,之后就能输出对应数据了。
至于为什么第一次使code_tmp = SEG[n3],这是因为三个SN74LS595N是采用级联的方式,前两个SN74LS595N移位寄存器溢出的值输出到了下一个SN74LS595N的SER端,所以第一次输出的数据最后到了最后一个SN74LS595N中。我们想要的效果就是n3显示在最后一个数码管上,所以移位的顺序是n3,n2,n1。
总结
现在看来数码管是否很简单呢,搞清楚了SN74LS595N的工作原理之后,代码其实也就这些,还有要注意的就是SEG[17]数组里面的值,这个也是要靠自己写出来的,要知道怎么写才行。最后希望大家蓝桥杯国赛取得一个好成绩。
以上是关于蓝桥杯嵌入式国赛模块训练之数码管的主要内容,如果未能解决你的问题,请参考以下文章