一、原理图
二、程序初始化
#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) 中断服务入口函数
}
}