7.DSP学习记录之74HC164驱动数码管
基于 TI 28335
一、数码管驱动简介
1.数码管简介

一位数码管由8个LED组成,数码管的显示,就是简单的高低电平输出
其连接方式有共阳极和共阴极两种,共阳极连接在数码管的连接端直接拉低电平即可,而共阴极接法需要使用驱动芯片进行驱动LED管使其导通
显示方式有动态显示和静态显示两种,静态显示即直接给LED电平,动态显示的原理主要是通过将所有数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。选亮数码管采用动态扫描显示。所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示
数码管的编码:
如图,数码管由8个LED组成,分别为:ABCDEFGH和dp符号位,将该8位进行二进制编码,以数字0为例,若采用共阴极接法,则需要导通ABCDEF,即0011 1111,化为16进制位为:0x3F,其他数字编码为 :

2.驱动芯片74HC164
74HC164芯片,该芯片是一种8位串并转换控制芯片,主要用于数字电路和LED显示控制电路应用,只需要2个单片机IO口就可以扩展出8个控制口,可通过此8个输出口控制数码管段选,对于4根位选(指的是选择哪一个数码管进行点亮)控制线可直接使用IO 口控制。
上图中:绿色为两个输入,黄色为8个输出
该芯片的驱动方式类似SPI通信
74HC164是8位边沿触发式移位寄存器,串行输入数据,然后并行输出。数据通过两个输入端(DSA
或DSB)之一串行输入;任一输入端可以用作高电平使能端,控制另一输入端的数据输入。两个输入端或者连接在一起,或者把不用的输入端接高电平,一定不要悬空
时钟(CP)每次由低变高时,数据右移一位,输入到Q0,Q0是两个数据输入端(DSA或DSB)的逻辑与(若要保持数据有效则要将一条线一直高电平),它将上升时钟沿之前保持一个建立时间的长度。
主复位(MR)输入端上的一个低电平将使其它所有输入端都无效,同时非同步地清除寄存器,强制所有的输出为低电平。
总结:当CLK 上升沿到来时数据输入端(A或B)数据传输进去,要将一个段码数据传输出去可循环8次逐位发送
二、点亮实验
1.电路连接



从上图:
数码管的驱动输入IO为:GPIO54、GPIO55
时钟线为:GPIO56
数码管段选IO为:GPIO70~~GPIO73
2.软件实现
实现效果:数码管循环显示 1314 和 520
数码管SMG.c配置文件:
#include "SMG.h"
#include "led.h"
unsigned char SMG_Table[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7d,0x07,0x7F,0x6F};
//数码管初始化
void SMG_Init(void)
{
EALLOW;
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK=1;//开启GPIO时钟
//SMG数据控制端口配置
GpioCtrlRegs.GPBMUX2.bit.GPIO56=0;
GpioCtrlRegs.GPBDIR.bit.GPIO56=1;
GpioCtrlRegs.GPBPUD.bit.GPIO56=0;
GpioCtrlRegs.GPBMUX2.bit.GPIO54=0;
GpioCtrlRegs.GPBDIR.bit.GPIO54=1;
GpioCtrlRegs.GPBPUD.bit.GPIO54=0;
GpioCtrlRegs.GPCMUX1.bit.GPIO70=0;
GpioCtrlRegs.GPCDIR.bit.GPIO70=1;
GpioCtrlRegs.GPCPUD.bit.GPIO70=0;
GpioCtrlRegs.GPCMUX1.bit.GPIO71=0;
GpioCtrlRegs.GPCDIR.bit.GPIO71=1;
GpioCtrlRegs.GPCPUD.bit.GPIO71=0;
GpioCtrlRegs.GPCMUX1.bit.GPIO72=0;
GpioCtrlRegs.GPCDIR.bit.GPIO72=1;
GpioCtrlRegs.GPCPUD.bit.GPIO72=0;
GpioCtrlRegs.GPCMUX1.bit.GPIO73=0;
GpioCtrlRegs.GPCDIR.bit.GPIO73=1;
GpioCtrlRegs.GPCPUD.bit.GPIO73=0;
EDIS;
GpioDataRegs.GPCCLEAR.bit.GPIO70=1;
GpioDataRegs.GPCCLEAR.bit.GPIO71=1;
GpioDataRegs.GPCCLEAR.bit.GPIO72=1;
GpioDataRegs.GPCCLEAR.bit.GPIO73=1;
}
//数码管显示函数
void SMG_DisplayInt(Uint16 num)
{
unsigned char buf[4];
unsigned char i=0;
buf[0] = SMG_Table[num/1000]; //取千位
buf[1] = SMG_Table[num%1000/100]; //取百位
buf[2] = SMG_Table[num%1000%100/10]; //取十位
buf[3] = SMG_Table[num%1000%100%10]; //取个位
//高位为0检测,本人屎山水平,请勿喷。。。
if((num/1000) == 0)
{
buf[0] = 0x00;
if((num%1000/100) == 0)
{
buf[1] = 0x00;
if((num%1000%100/10) == 0)
{
buf[2] = 0x00;
}
}
}
for(i=0;i<4;i++)
{
HC164SendData(buf[i]);
switch(i)
{
case 0:SEG1_H;SEG2_L;SEG3_L;SEG4_L;break;
case 1:SEG1_L;SEG2_H;SEG3_L;SEG4_L;break;
case 2:SEG1_L;SEG2_L;SEG3_H;SEG4_L;break;
case 3:SEG1_L;SEG2_L;SEG3_L;SEG4_H;break;
}
DELAY_US(5000);
}
}
//74HC164数据发送函数
//dat:所要发送的数据
void HC164SendData(unsigned char dat)
{
char i=0;
for(i=0;i<8;i++)
{
CLK_L;
if(dat & 0x80)
{
SPI_SIMOA_H;
}
else
{
SPI_SIMOA_L;
}
CLK_H; //SPI总线在脉冲上升延传输数据
dat<<=1; //数据左移一位
}
}
SMG.h文件:
/*
* SMG.h
*
* Created on: 2025年10月13日
* Author: dzg
*/
#ifndef HARDWARE_SMG_H_
#define HARDWARE_SMG_H_
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h" // DSP2833x Examples Include File#include "beep.h"
//数码管段选宏定义
#define SEG1_H (GpioDataRegs.GPCSET.bit.GPIO70=1)
#define SEG1_L (GpioDataRegs.GPCCLEAR.bit.GPIO70=1)
#define SEG2_H (GpioDataRegs.GPCSET.bit.GPIO71=1)
#define SEG2_L (GpioDataRegs.GPCCLEAR.bit.GPIO71=1)
#define SEG3_H (GpioDataRegs.GPCSET.bit.GPIO72=1)
#define SEG3_L (GpioDataRegs.GPCCLEAR.bit.GPIO72=1)
#define SEG4_H (GpioDataRegs.GPCSET.bit.GPIO73=1)
#define SEG4_L (GpioDataRegs.GPCCLEAR.bit.GPIO73=1)
//驱动芯片宏定义
#define CLK_H (GpioDataRegs.GPBSET.bit.GPIO56=1)
#define CLK_L (GpioDataRegs.GPBCLEAR.bit.GPIO56=1)
#define SPI_SIMOA_H (GpioDataRegs.GPBSET.bit.GPIO54=1)
#define SPI_SIMOA_L (GpioDataRegs.GPBCLEAR.bit.GPIO54=1)
void SMG_Init(void);
void SMG_DisplayInt(Uint16 num);
void HC164SendData(unsigned char dat);
#endif /* HARDWARE_SMG_H_ */
主函数:
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h" // DSP2833x Examples Include File
#include "beep.h"
#include "Key.h"
#include "led.h"
#include "Interrupt.h"
#include "SMG.h"
void main()
{
InitSysCtrl();
Led_Init();
SMG_Init();
int i;
while(1)
{
i = 100;
while(i--)//i = 0时跳出循环
{
SMG_DisplayInt(1314);
}
i = 100;
while(i--)
{
SMG_DisplayInt(520);
}
}
}
三、28335数码管倒计时秒表
注意要将Count声明为全局变量
一个小倒计时秒表,可以通过按键调节计时时间,计时到0后停止
main.c:
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h" // DSP2833x Examples Include File
#include "beep.h"
#include "Key.h"
#include "led.h"
#include "Interrupt.h"
#include "SMG.h"
void main()
{
InitSysCtrl();
InitPieCtrl();
IER=0x0000;
IFR=0x0000;
InitPieVectTable();
Key_Init();
Led_Init();
SMG_Init();
while(1)
{
switch(Key_Scan(0))
{
case 1:Count++;break;
case 2:Count--;break;
case 3:Tim0_Init(150,1000000);;break;
}
SMG_DisplayInt(Count);
}
}
定时器配置:
#include "Interrupt.h"
#include "led.h"
unsigned char Count = 10;
interrupt void TIM0_IRQn(void)
{
EALLOW;
Count = Count - 1;
if(Count == 0)
{
InitPieCtrl();
IER=0x0000;
IFR=0x0000;
InitPieVectTable();
}
PieCtrlRegs.PIEACK.bit.ACK1=1;
EDIS;
}
void Tim0_Init(float Freq, float Period)
{
//1.时钟初始化
EALLOW;
SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;
EDIS;
//2.初始化定时器参数
CpuTimer0.RegsAddr=&CpuTimer0Regs;//指向定时器0的寄存器地址
CpuTimer0Regs.PRD.all =0xFFFFFFFF; //设置定时器0的周期寄存器值
CpuTimer0Regs.TPR.all =0;//设置定时器预定标计数器值为0
CpuTimer0Regs.TPRH.all=0;
CpuTimer0Regs.TCR.bit.TSS=1; //确保定时器0为停止状态
CpuTimer0Regs.TCR.bit.TRB=1; //重载使能
CpuTimer0.InterruptCount=0; //Resetinterruptcounters:
//3.定时器定时周期以及设置定时器的控制寄存器等
ConfigCpuTimer(&CpuTimer0,Freq,Period);
//4.设置定时器0的中断入口地址为中断向量表的INT0
EALLOW;
PieVectTable.TINT0=&TIM0_IRQn;
EDIS;
//5.开启定时器中断功能,并使能定时器
CpuTimer0Regs.TCR.bit.TSS=0; //开始定时器功能
PieCtrlRegs.PIEIER1.bit.INTx7=1;//PIE级中断使能,第一组中断的第7个小中断,即定时器0
//使能CPU总中断
IER|=M_INT1;
EINT;
ERTM;
}
数码管配置同上
更多推荐


所有评论(0)