Files
2026-10-19 15:47:18 +08:00

193 lines
4.8 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "led_digital_tube.h"
#include "bitband.h"
#include "systick.h"
// 显示文字内容表
static u8 table[] = {
0x3f,0x06,0x5b,0x4f, // 0 1 2 3
0x66,0x6d,0x7d,0x07, // 4 5 6 7
0x7f,0x6f,0x77,0x7c, // 8 9 A b
0x39,0x5e,0x79,0x71 // C d E F
};
// HC138 管脚位段定义
#define HC138_A0 PCOut(11)
#define HC138_A1 PCOut(12)
#define HC138_A2 PCOut(2)
// HC595 管脚位段定义
#define HC595_DATA PBOut(3) // 接 DS 管脚
#define HC595_LCLK PBOut(4) // 接 ST_CP 管脚
#define HC595_SCLK PBOut(5) // 接 SH_CP 管脚
// 初始化数码管
void led_digital_tube_init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
// 开启 GPIO 相关的时钟
RCC_APB2PeriphClockCmd(
RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC |
RCC_APB2Periph_GPIOD |
RCC_APB2Periph_AFIO,
ENABLE);
// 保留 SWD 调试能力的前提下
// 将 PB3/PB4/PA15 这三个管脚从 JTAG 功能中释放出来
// 作为普通 GPIO 使用,从而有效的增加项目可用 I/O 数量
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
// 使能 HC138 芯片管脚 (PC11/PC12/PD2)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_Init(GPIOD, &GPIO_InitStruct);
// 初始化 HC595 芯片使用的管脚(PB3/PB4/PB5)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
// hc138 设置地址
void hc138_out_data(u8 data)
{
switch (data)
{
case 0:
HC138_A2 = 0;
HC138_A1 = 0;
HC138_A0 = 0;
break;
case 1:
HC138_A2 = 0;
HC138_A1 = 0;
HC138_A0 = 1;
break;
case 2:
HC138_A2 = 0;
HC138_A1 = 1;
HC138_A0 = 0;
break;
case 3:
HC138_A2 = 0;
HC138_A1 = 1;
HC138_A0 = 1;
break;
default:
break;
}
}
// hc595 发送数据
void hc595_send_data(u8 data)
{
// 循环变量
uint8_t i =0;
// 高位先发送,SH_CP 位低电平时变化数据
// SH_CP 的上升沿会将 DS 数据放入移位寄存器并移位
for (i = 0; i < 8; i++)
{
// SH_CP 管脚拉低并准备发送数据
HC595_SCLK = 0;
// 根据数据的最高位来变化 DS 数据线
if (data & 0x80)
{
HC595_DATA = 1;
} else {
HC595_DATA = 0;
}
// 左移 1位,丢掉最高位
data <<= 1;
// 上升沿锁定一个位到移位寄存器
HC595_SCLK = 1;
}
// 8 个数据位发送结束,将 HC595 从低到高(制造一个上升沿)
HC595_LCLK = 0;
// delay_ms(1);
// 上升沿
HC595_LCLK = 1;
}
// 数码管显示 4 位整数(低四位)
void led_digital_show_interger(int data)
{
uint8_t buf[4] ={0};
uint8_t i = 0;
// 计算千位
buf[0] = data / 1000 % 10;
// 计算百位
buf[1] = data / 100 % 10;
// 计算十位
buf[2] = data / 10 % 10;
// 计算个位
buf[3] = data / 1 % 10;
// 循环显示 4 位数据
for ( i = 0; i < 4; i++)
{
// 设置哪个晶体管亮(0时最左侧亮)
hc138_out_data(i);
// 显示数字
hc595_send_data(table[buf[i]]);
// hc595_send_data(0xFF);
// 停留 1ms
delay_ms(1);
// 熄灭
hc595_send_data(0);
}
}
// 数码管显示 4 位小数(ndigit 表示小数点后保留有数位数 0~3 位)
void led_digital_show_float(float value, int ndigit/* 小数位数 0~3 */)
{
uint8_t buf[4] ={0};
uint8_t i = 0;
float temp = value;
int data;
// 如果小数点位数不在合法范围内
// 则让小数点放在最右边(小数部分位 0 位)
if (ndigit > 3 || ndigit < 0)
{
ndigit = 0;
}
// 将 temp 扩大 10的 ndigit 次方倍
for (i = 0; i < ndigit; i++)
{
temp *= 10;
}
data = temp;
buf[0] = data / 1000 % 10;
buf[1] = data / 100 % 10;
buf[2] = data / 10 % 10;
buf[3] = data / 1 % 10;
// 循环显示 4 位数据
for ( i = 0; i < 4; i++)
{
// 设置哪个晶体管亮(0时最左侧亮)
hc138_out_data(i);
// 显示数字
hc595_send_data(table[buf[i]] | (i == 3 - ndigit ? 0x80 : 0x00));
// hc595_send_data(0xFF);
// 停留 1ms
delay_ms(1);
// 熄灭
hc595_send_data(0);
}
}