【STM32】 数码管驱动

一、简单介绍

数码管驱动电路如图所示,笔者选用安世半导体生产的74HC138D和74HC595D芯片驱动共阴极数码管。原理图如下:

数码管

四位贴片共阴极数码管,6、8、9、12分别是四个数码管的阴极。单看每一个数字,由8个发光二极管组成,这些二极管的阴极是连在一起的。

abcdefg等代表四个数码管的每一个短线(小数点)。当其中段选一个高电平,同时位选是低电平,发光二极管导通,对应的短线就会亮起来。

74HC138D

74HC138D具有3条地址线和8个输出,唯有E1和E2均为低电平且E3是高电平,输出才不会都是高(大部分使用场景)。

真值表和逻辑框图如上。输入A2是高位,输出Y7是高位。

如果要4个数码管的阴极输出低电平,Y3=0 -> A2A1A0 = 3 -> 0b011。

74HC595D

74HC595是8bit的串行输入,并行输出寄存器芯片,移位和存储具有单独的时钟(SHCP引脚或者STCP引脚的上升沿)。

SHCP上升沿:数据移位,会频繁触发。

STCP上升沿:将移位寄存器的数据搬运到存储寄存器,偶尔触发。

OE控制输出:当OE为低时,存储寄存器的值体现在输出引脚上,OE为高时,输出引脚高阻态。

Q7S是为级联提供便利而设置的。

观察时序图,发现在SHCP的上升沿,对DS引脚电平采样,把DS电平存放在内部寄存器(每来一个SHCP上升沿,内部寄存器就移位一次),当STCP上升沿,内部寄存器输出到Q0~Q7引脚上(OE为低电平)。

例如显示"1"那么"b"和"c"是高电平,其余是低电平。

abcdefgh输出值0b0110 0000亦即0x60。

每来一个SHCP上升沿,数据就会移位一次,因此Q7是第一次采样时DS值,连接到数码管的DPX引脚。以此类推,Q2是第5次采样(c),Q2是第6次采样(b)。

二、驱动代码

cpp 复制代码
#define DIGITAL_A0_LOW()       HAL_GPIO_WritePin(A0_GPIO_Port,A0_Pin,GPIO_PIN_RESET)
#define DIGITAL_A0_HIGH()      HAL_GPIO_WritePin(A0_GPIO_Port,A0_Pin,GPIO_PIN_SET)

#define DIGITAL_A1_LOW()        HAL_GPIO_WritePin(A1_GPIO_Port,A1_Pin,GPIO_PIN_RESET)
#define DIGITAL_A1_HIGH()       HAL_GPIO_WritePin(A1_GPIO_Port,A1_Pin,GPIO_PIN_SET)

#define DIGITAL_A2_LOW()        HAL_GPIO_WritePin(A2_GPIO_Port,A2_Pin,GPIO_PIN_RESET)
#define DIGITAL_A2_HIGH()       HAL_GPIO_WritePin(A2_GPIO_Port,A2_Pin,GPIO_PIN_SET)

#define DIGITAL_A3_LOW()        HAL_GPIO_WritePin(A3_GPIO_Port,A3_Pin,GPIO_PIN_RESET)
#define DIGITAL_A3_HIGH()       HAL_GPIO_WritePin(A3_GPIO_Port,A3_Pin,GPIO_PIN_SET)

#define DIGITAL_SER_LOW()       HAL_GPIO_WritePin(SER_GPIO_Port,SER_Pin,GPIO_PIN_RESET)
#define DIGITAL_SER_HIGH()      HAL_GPIO_WritePin(SER_GPIO_Port,SER_Pin,GPIO_PIN_SET)

#define DIGITAL_DISEN_LOW()        HAL_GPIO_WritePin(DISEN_GPIO_Port,DISEN_Pin,GPIO_PIN_RESET)
#define DIGITAL_DISEN_HIGH()       HAL_GPIO_WritePin(DISEN_GPIO_Port,DISEN_Pin,GPIO_PIN_SET)

#define DIGITAL_SHCP()      do{HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);} while (0)

#define DIGITAL_STCP()      do{HAL_GPIO_WritePin(DISLK_GPIO_Port, DISLK_Pin, GPIO_PIN_RESET);HAL_GPIO_WritePin(DISLK_GPIO_Port, DISLK_Pin, GPIO_PIN_SET);} while (0)
cpp 复制代码
const uint8_t DigitalNum_Table[] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6,0xEE,0x3E,0x9C,0x7A,0x9E,0x8E, 0x00, 0x02};

void Digital_Show(uint8_t num, uint8_t point)
{
   uint8_t number = DigitalNum_Table[num];
   if (point == 1)
   {
      number++;
   }
   
   DIGITAL_DISEN_HIGH();
   for (uint8_t i = 0; i < 8; i++)
   {
      if ((number >> i) & 0x01 == 0x01)
      {
         DIGITAL_SER_HIGH();
      }
      else
      {
         DIGITAL_SER_LOW();
      }
      DIGITAL_SHCP();
   }
   DIGITAL_STCP();
   DIGITAL_DISEN_LOW();
}

定义数字显示结构体类型:

cpp 复制代码
typedef struct 
{
   int8_t number;
   uint8_t point;
}DigitalType;

周期调用数码管位选函数,配合单个数字显示,就可以动态扫描显示。

cpp 复制代码
void Digital_CC(uint8_t channel)
{
   Digital_Show(numbers[channel].number, numbers[channel].point);
   switch (channel)
   {
      case 0:
      {
         DIGITAL_A0_LOW();
         DIGITAL_A1_LOW();
         DIGITAL_A2_LOW();
         break;
      }
      case 1:
      {
         DIGITAL_A0_HIGH();
         DIGITAL_A1_LOW();
         DIGITAL_A2_LOW();
         break;
      }
      case 2:
      {
         DIGITAL_A0_LOW();
         DIGITAL_A1_HIGH();
         DIGITAL_A2_LOW();
         break;
      }
      case 3:
      {
         DIGITAL_A0_HIGH();
         DIGITAL_A1_HIGH();
         DIGITAL_A2_LOW();
         break;
      }
      default:
         break;
   }
}

想要显示什么数字,就设置结构体数组的内容。

cpp 复制代码
/**
 * @param num means number
 * @param pointPos which number have point,if -1 means no point
 */
void Digital_ShowNumber(int16_t num, uint8_t pointPos)
{
   for (uint8_t i = 0; i < 4; i++)
   {
      numbers[i].number = 16;
      numbers[i].point = 0;
   }
   if (pointPos != -1)
   {
      numbers[pointPos].point = 1;
   }
   
   
   if (num >= 0)
   {
      if (num < 10)
      {
         numbers[3].number = num;
      }
      else if (num < 100)
      {
         /* 99 */
         numbers[2].number = num / 10 % 10;
         numbers[3].number = num % 10;
      }
      else if (num < 1000)
      {
         /* 999 */
         numbers[1].number = num / 100 % 10;
         numbers[2].number = num / 10 % 10;
         numbers[3].number = num % 10;
      }
      else if (num < 10000)
      {
         /* 9999 */
         numbers[0].number = num / 1000 % 10;
         numbers[1].number = num / 100 % 10;
         numbers[2].number = num / 10 % 10;
         numbers[3].number = num % 10;
      }
      else
      {

      }
   }
   else
   {
      num = 0 - num;
      if (num < 10)
      {
         numbers[2].number = 17;
         numbers[3].number = num;
      }
      else if (num < 100)
      {
         /* 99 */
         numbers[1].number = 17;
         numbers[2].number = num / 10 % 10;
         numbers[3].number = num % 10;
      }
      else if (num < 1000)
      {
         /* 999 */
         numbers[0].number = 17;
         numbers[1].number = num / 100 % 10;
         numbers[2].number = num / 10 % 10;
         numbers[3].number = num % 10;
      }
      else
      {

      }
   }
}
相关推荐
up向上up2 小时前
基于51单片机垃圾箱自动分类加料机快递物流分拣器系统设计
单片机·嵌入式硬件·51单片机
纳祥科技11 小时前
Switch快充方案,内置GaN,集成了多个独立芯片
单片机
单片机日志13 小时前
【单片机毕业设计】【mcugc-mcu826】基于单片机的智能风扇系统设计
stm32·单片机·嵌入式硬件·毕业设计·智能家居·课程设计·电子信息
松涛和鸣13 小时前
从零开始理解 C 语言函数指针与回调机制
linux·c语言·开发语言·嵌入式硬件·排序算法
小曹要微笑20 小时前
STM32F7 时钟树简讲(快速入门)
c语言·stm32·单片机·嵌入式硬件·算法
XINVRY-FPGA20 小时前
XCVP1802-2MSILSVC4072 AMD Xilinx Versal Premium Adaptive SoC FPGA
人工智能·嵌入式硬件·fpga开发·数据挖掘·云计算·硬件工程·fpga
沐欣工作室_lvyiyi20 小时前
家用按摩椅控制系统设计(论文+源码)
单片机·物联网·毕业设计·按摩椅控制系统
天天爱吃肉82181 天前
电机控制技术深度解析:从基础原理到前沿实战
python·嵌入式硬件·汽车