STM8S103学习之旅——一个74HC164驱动4位数码管

文章描述了一个基于STM8S微控制器的系统初始化过程,包括GPIO端口配置,用于74HC164的数据传输和数码管显示。此外,还涉及了按键初始化,定时器4的设置以实现毫秒级中断,以及中断服务函数,特别是对按键中断的处理。程序通过定时器中断来循环显示数码管内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、原理图

 

二、程序初始化

#include "int.h"
u8 const Data[17] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};
u8 ms_count ,  SMGBit;


//74HC164 GPIO口初始化
void NumericDisplay_Init()
{
  //设置PA1为输出 ,HC164 CLK
  GPIO_Init(GPIOA , GPIO_PIN_1 , GPIO_MODE_OUT_PP_LOW_FAST);  
    
  //设置PA2为输出 ,HC164DAT
  GPIO_Init(GPIOA , GPIO_PIN_2 , GPIO_MODE_OUT_PP_LOW_FAST);  
    
  //设置PC3为输出 ,位码数
  GPIO_Init(GPIOC , GPIO_PIN_3 , GPIO_MODE_OUT_PP_LOW_FAST);  
    
  //设置PC2为输出 ,位码2
  GPIO_Init(GPIOC , GPIO_PIN_2 , GPIO_MODE_OUT_PP_LOW_FAST);  
    
  //设置PC5为输出 ,位码3
  GPIO_Init(GPIOC , GPIO_PIN_5 , GPIO_MODE_OUT_PP_LOW_FAST);  
    
  //设置PC1为输出 ,位码4
  GPIO_Init(GPIOC , GPIO_PIN_1 , GPIO_MODE_OUT_PP_LOW_FAST);  
    
     CLK_ReSet();
  
}

//按键初始化  key2为外部最高中断,开启中断复用
void KEY2Init()
{
  EXTI_SetTLISensitivity(EXTI_TLISENSITIVITY_FALL_ONLY); //TLI引脚为下降沿触发中断
  
  //外部高级中断引脚TLI PD->7的输入输出方向寄存器为输入方向 , 上拉电阻输入 , 使能外部中断
  GPIO_Init(GPIOD , GPIO_PIN_7 , GPIO_MODE_IN_PU_IT);
}


//key1、key2按键初始化,普通按键输入
void KEYInit()
{
  //GPA->PIN3 设置为输入模式 , 上拉电阻输入 , 禁止外部中断
  GPIO_Init(KEY1_PORT , KEY1_PIN , GPIO_MODE_IN_PU_NO_IT);  
  //GPIO_Init(KEY2_PORT , KEY2_PIN , GPIO_MODE_IN_PU_NO_IT);  
  GPIO_Init(KEY3_PORT , KEY3_PIN , GPIO_MODE_IN_PU_NO_IT);  
  
  
}


void Timer4Init()
{
 
  TIM4_TimeBaseInit(TIM4_PRESCALER_128 ,  //定时器4时钟 = 16MHz / 128 = 125KHZ 
                    125                   //设定定时器产生1毫秒重装载时的计数值125,255是最大值
                    );
  TIM4_ITConfig(TIM4_IT_UPDATE , ENABLE); //使能定时器4更新中断
  TIM4_ARRPreloadConfig(ENABLE);          //允许自动仲裁
  TIM4_Cmd(ENABLE);                       //启动定时器4开始计数

}

 二、初始化头文件

#ifndef __INT_H
#define __INT_H

#include "stm8s.h"

extern u8 i;

extern u8 BUF;

//按键定义
#define KEY1_PIN        GPIO_PIN_3   //定义要使用端口的第四个管脚
#define KEY1_PORT       GPIOA        //定义E端口,方便程序修改及可移植性好

#define KEY2_PIN        GPIO_PIN_7   //
#define KEY2_PORT       GPIOD     

#define KEY3_PIN        GPIO_PIN_6   //
#define KEY3_PORT       GPIOC    


void KEYInit();
void KEY2Init();


//数码管0 ~ F的代码数组  数码管定义

 #define     SMG_1_ON()    GPIO_WriteHigh(GPIOC , GPIO_PIN_3)    
 #define     SMG_2_ON()    GPIO_WriteHigh(GPIOC , GPIO_PIN_2)  
 #define     SMG_3_ON()    GPIO_WriteHigh(GPIOC , GPIO_PIN_5)  
 #define     SMG_4_ON()    GPIO_WriteHigh(GPIOC , GPIO_PIN_1)  

 #define     SMG_1_OFF()   GPIO_WriteLow(GPIOC , GPIO_PIN_3)
 #define     SMG_2_OFF()   GPIO_WriteLow(GPIOC , GPIO_PIN_2)
 #define     SMG_3_OFF()   GPIO_WriteLow(GPIOC , GPIO_PIN_5)
 #define     SMG_4_OFF()   GPIO_WriteLow(GPIOC , GPIO_PIN_1)

#define     CLK_Set()     GPIO_WriteHigh(GPIOA , GPIO_PIN_1) 
#define     CLK_ReSet()   GPIO_WriteLow(GPIOA , GPIO_PIN_1) 

#define     DAT_Set()     GPIO_WriteHigh(GPIOA , GPIO_PIN_2) 
#define     DAT_ReSet()   GPIO_WriteLow(GPIOA , GPIO_PIN_2) 
 
extern u8 ms_count ,  SMGBit,i;//SMGtimes;

extern u8 const Data[17];

void NumericDisplay_Init();
void Timer4Init();

#endif /* __INT_H*/

 三、GPIO处理程序


/164传输位程序

void HC164D_WriteByte(unsigned char byte)
{
  unsigned char i;
  
  for(i = 0 ; i < 8 ; i++)
  {
    CLK_ReSet();
    if(byte & 0x80)
    {
      DAT_Set();
    }
    else
    {
       DAT_ReSet();
    }
     CLK_Set(); 
    byte <<= 1;
  }
   CLK_ReSet();
}

//164传输数据程序  ,,因为只有一个164,所以164不仅自己负责传输数据,还要传输4位数码管的位码
void HC164D_WriteData(unsigned char num, unsigned char show_bit)
{
	HC164D_WriteByte(num);
	HC164D_WriteByte(show_bit);  
	
	    
}

void delay(unsigned int ms)
{
  unsigned int x , y;
  for(x = ms; x > 0; x--)           /*  通过一定周期循环进行延时*/
    for(y = 3000 ; y > 0 ; y--);
}


//数码管通过定时器不断的++均匀显示


 INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23)
 {
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
  if(TIM4_GetITStatus(TIM4_IT_UPDATE) == SET )
  {
    TIM4_ClearFlag(TIM4_FLAG_UPDATE);   //清除中断标志
    ms_count++;           //中断使 ms_count++ 做加法,记录1毫秒产生的中断次数
    if(ms_count >= 5)
    {
      ms_count = 0;
    
        SMG_1_OFF();
        SMG_2_ON();
        SMG_3_OFF();
        SMG_4_OFF();
        SMGBit = 0;

    }
  HC164D_WriteData(SMGBit, Data[i]);
  if(GPIO_ReadInputPin(GPIOC , GPIO_PIN_6) == RESET)      //如果KEY2被按下
    {
      delay(10);                     //先延时进行消抖
      while(GPIO_ReadInputPin(GPIOC , GPIO_PIN_6) == RESET);    //等待按钮被松开
      delay(10);                     //再次延时消抖
      i++;
   }
  }
 }

//按键key2中断处理
INTERRUPT_HANDLER(TLI_IRQHandler, 0)

{
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
  BUF = 1;
}

四、处理程序的头文件

#ifndef __DEAL_H
#define __DEAL_H


#include "int.h"


void HC164D_WriteByte(unsigned char byte);
void HC164D_WriteData(unsigned char num, unsigned char show_bit);
INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23);




#endif /* __DEAL_H*/

 

五、主程序

#include “deal.h”


int main(void)
{
  
  disableInterrupts();    //先禁止系统总中断
  //内部时钟为1分频 = 16Mhz
  CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
  NumericDisplay_Init();
  KEYInit();
  KEY2Init();
  InitLED();

  Timer4Init(); 
  LEDCLOSE();
  halt();
 
  enableInterrupts();  //使能系统总中断

  while(1)
  {
      

    //利用定时器4的周期中断,扫描4位数码管,中断服务函数在stm8s_it.c文件里的  INTERRUPT_HANDLER(TIM4_UPD_OVF_IRQHandler, 23) 中断服务入口函数
  }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值