#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); } }