在MSPM0L1306微控制器上使用74HC595移位寄存器来驱动数码管并实现读秒功能,
以下步骤:
硬件连接
将MSPM0L1306的GPIO引脚连接到74HC595的输入引脚:数据输入(DIO)、移位寄存器时钟输入(SHCP)和存储寄存器时钟输入(STCP)。
将74HC595的输出引脚连接到数码管的段选和位选引脚。
如果数码管是共阳的,你还需要一个公共端连接到正电源(VCC),并通过适当的电阻限制电流。如果是共阴的,公共端连接到地(GND)。
根据设计,需要使用额外的GPIO引脚来控制数码管的位选。
上面说的好像不是那么回事,还是要来点实在的,上面的都略过。
DIO--PA4
RCLK--PA5--STCP
CLK--PA6--SHCP
VCC--3.3V
IC的各引脚定义:
引脚功能定义:
各引脚的电平描述:
. 编写驱动函数
根据74HC595的时序编写函数将数据发送到74HC595,操作GPIO引脚,点亮数码管。
时序图:
4. 实现数码管显示
根据数码管的编码表,为每个数字(0-9)准备一个字节的数据。
编写一个函数来根据给定的数字选择正确的段选数据,并使用位选来控制哪个数码管显示。
数码管原理:
显示对应的编码:
显示字段对照表:
数码管原理图:
软件实现方法:
74HC595芯片来驱动8位共阳极数码管时,其中一个74HC595用于数据移位(数据寄存器),而另一个用于片选(可能是通过另一个GPIO引脚直接控制,或者使用第二个74HC595的某个输出作为片选信号)。
以下是驱动步骤:
. 初始化GPIO
初始化GPIO引脚,包括用于数据输入的PA4(连接到第一个74HC595的DIO),两个时钟引脚(SHCP和STCP),以及可能用于片选的GPIO引脚。
. 数据传输到第一个74HC595(数据寄存器)
将需要显示的8位数据通过PA4引脚串行发送到第一个74HC595的数据输入(DIO)引脚。
使用L1306的GPIO引脚(连接到SHCP)生成8个上升沿,每个上升沿将DI上的下一位数据移入移位寄存器。先送高位,后送低位。
. 数据从移位寄存器传输到存储寄存器
使用L1306的GPIO引脚(连接到STCP)生成一个上升沿,将移位寄存器中的数据传输到存储寄存器中。
. 控制OE引脚
将第一个74HC595的OE引脚设置为低电平,以允许存储在存储寄存器中的数据从Q0到Q7并行输出。
. 数码管显示
根据数码管的编码表,为每个数字(0-9)准备一个字节的数据,并将其发送到第一个74HC595。
通过片选控制选择需要显示的数码管,并确保OE引脚处于低电平状态以允许数据输出。
. 周期性更新显示
使用L1306的定时器或软件延时来周期性地更新数码管的显示。
递增秒数变量,并在需要时重置为0并递增分钟数。
. 主循环
在主循环中,不断地检查是否需要更新数码管的显示,并调用相应的函数来更新。
学习GPIO的输出配置,驱动74HC595数码管显示
CCS配置数码管引脚:
#define DELAY (16000000)
#define HC595_DAT(x) ((x)?( DL_GPIO_setPins(GPIO_LEDS_PORT,GPIO_LEDS_HC595_DAT_PIN)):( DL_GPIO_clearPins(GPIO_LEDS_PORT,GPIO_LEDS_HC595_DAT_PIN) ))
#define HC595_CLK(x) ((x)?( DL_GPIO_setPins(GPIO_LEDS_PORT,GPIO_LEDS_HC595_CLK_PIN)):( DL_GPIO_clearPins(GPIO_LEDS_PORT,GPIO_LEDS_HC595_CLK_PIN) ))
#define HC595_RCK(x) ((x)?( DL_GPIO_setPins(GPIO_LEDS_PORT,GPIO_LEDS_HC595_RCK_PIN)):( DL_GPIO_clearPins(GPIO_LEDS_PORT,GPIO_LEDS_HC595_RCK_PIN) ))
uint16_t keyTmep;
uint16_t DutyTmep = 0;
uint16_t i,j;
uint8_t dir = 1;
uint8_t Disp_DX[ 16 ] = { 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x8C,0xBF,0xC6,0xA1,0x86,0xFF };
uint8_t Disp_PX[ 8 ] = {1,2,3,4,5,6,7,8};
void Display_Out()
{
delay_cycles(1000);
HC595_RCK(0);
delay_cycles(1000);
HC595_RCK(1);
}
void HC595_WriteData(uint8_t data)
{
uint8_t i;
for(i = 0;i < 8;i++)
{
if (data & 0x80)
{
HC595_DAT(1);
}
else
{
HC595_DAT(0);
}
data <<= 1;
delay_cycles(1000);
HC595_CLK(0);
delay_cycles(1000);
HC595_CLK(1);
}
}
void HC595_SEND_DATA(uint8_t dis_num, uint8_t dis_bit)
{
HC595_WriteData(dis_num);
HC595_WriteData(1<<dis_bit);
Display_Out();
}
void Disp_Data(uint16_t dataH,uint16_t dataL)
{
uint16_t tempH,tempL ;
uint8_t num_q,num_b,num_s,num_g;
tempL = dataL;
num_q = tempL/1000;
num_b = tempL/100%10;
num_s = tempL/10%10;
num_g = tempL%10;
HC595_SEND_DATA(Disp_DX[num_q],3);
HC595_SEND_DATA(Disp_DX[num_b],2);
HC595_SEND_DATA(Disp_DX[num_s],1);
HC595_SEND_DATA(Disp_DX[num_g],0);
tempH = dataH;
num_q = tempH/1000;
num_b = tempH/100%10;
num_s = tempH/10%10;
num_g = tempH%10;
HC595_SEND_DATA(Disp_DX[num_q],7);
HC595_SEND_DATA(Disp_DX[num_b],6);
HC595_SEND_DATA(Disp_DX[num_s],5);
HC595_SEND_DATA(Disp_DX[num_g],4);
}
int main(void)
{
/* Power on GPIO, initialize pins as digital outputs */
SYSCFG_DL_init();
delay_cycles(10000);
while (1) {
Disp_Data(1234,5678);
}
}
学习GPIO的输入配置,实现按键控制数码管数据的变化
按键控制数码管:
int main(void)
{
/* Power on GPIO, initialize pins as digital outputs */
SYSCFG_DL_init();
delay_cycles(10000);
uint16_t keyTmep;
uint16_t DutyTmep = 0;
uint16_t i=0,j=0;
uint8_t dir = 1;
uint16_t KeyTmp;
uint16_t TmpVal = 0;
uint16_t KeyBounce = 0;
while (1) {
keyTmep = DL_GPIO_readPins(GPIO_LEDS_PORT,KEY_SW1_PIN);
delay_cycles(10);
keyTmep = DL_GPIO_readPins(GPIO_LEDS_PORT,KEY_SW1_PIN);
if(keyTmep == 0)
{
KeyBounce ++;
if(KeyBounce >= 100)
{
TmpVal++;
KeyBounce = 0;
}
if(TmpVal > 9999)
{
TmpVal += 10;
}
}
Disp_Dataa(TmpVal);
}}
学习定时器的配置,实现数字秒表
定时器控制数码管:
void TIMER_0_INST_IRQHandler(void)
{
switch (DL_TimerG_getPendingInterrupt(TIMER_0_INST)) {
case DL_TIMER_IIDX_ZERO:
TimerCnt++;
if(TimerCnt >= 100)
{
TimerCnt = 0;
TmpVal++;
if(TmpVal > 500)TmpVal=0;
}
break;
default:
break;
}
}
int main(void)
{
uint16_t keyTmep;
uint16_t DutyTmep = 0;
uint16_t i=0,j=0;
uint8_t dir = 1;
uint16_t KeyTmp;
uint16_t TmpVal = 0;
uint16_t KeyBounce = 0;
/* Power on GPIO, initialize pins as digital outputs */
SYSCFG_DL_init();
delay_cycles(10000);
NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN);
while (1) {
Disp_Dataa(TmpVal);
}
}
用定时器中断实现数码管数值的递减:
void TIMER_0_INST_IRQHandler(void)
{
switch (DL_TimerG_getPendingInterrupt(TIMER_0_INST)) {
case DL_TIMER_IIDX_ZERO:
// 递减 TimerCnt,但避免它变成负数
if (TimerCnt > 0) {
TimerCnt--;
}
// 如果 TimerCnt 递减到 0(或某个其他你设定的阈值),则递减 TmpVal
if (TimerCnt == 0) {
// 重置 TimerCnt 为某个初始值(比如 99),以便它再次开始递减
TimerCnt = 99; // 或者你想要的任何其他初始值
// 递减 TmpVal,但避免它变成负数
if (TmpVal > 0) {
TmpVal--;
}
// 如果需要,当 TmpVal 递减到 0 时,可以将其重置为某个初始值
if (TmpVal == 0) {
TmpVal = 500; // 或者你想要的任何其他初始值
}
}
break;
default:
break;
}
}