一、六位数码管详解
我用的是六位共阳极数码管,一般来说数码管是8个引脚控制每个方块的8个灯管(包括小数点),另外6个引脚控制当前是第几个灯块亮起,具体可以自己连上高低电平看看。
对于共阳数码管来说,控制每个灯块的引脚(这里记作GPIO1或GPIO2等)如果是高电平则对这个灯块进行操作。控制每个灯管的引脚(这里记作GPIO_a或GPIO_b等)如果是低电平则点亮,高电平则熄灭。
好了,现在已经知道工作原理了,不知道的孩子们自己试一下就知道了。接3.3V的电平不会爆掉,可以随意尝试。接5V的电平可能就寄了,请谨慎带电操作!!!
二、STM32G4点亮数码管
1.Cubemx配置
超简单配置,选择你喜欢的14个引脚把他们一口气变成OUTPUT模式就可以。
最后总体长这样子,随意选择即可。这里我选择的具体OUTPUT模式是推挽输出。
2.代码呈现
先附上代码:
#define GPIO_LOW GPIO_PIN_RESET
#define GPIO_HIGH GPIO_PIN_SET
typedef struct Pin {
GPIO_TypeDef* port;
uint16_t pin;
} Pin;
Pin allPins[20] = {
{NULL, 0}, {GPIOA, GPIO_PIN_10}, {GPIOC, GPIO_PIN_5}, {GPIOB, GPIO_PIN_3}, {GPIOB, GPIO_PIN_10}, {GPIOB, GPIO_PIN_5}, {GPIOA, GPIO_PIN_9}, {GPIOC, GPIO_PIN_4}, {GPIOB, GPIO_PIN_4},
};
Pin control[10] = {
{GPIOA, GPIO_PIN_8}, {GPIOC, GPIO_PIN_7}, {GPIOB, GPIO_PIN_6}, {GPIOA, GPIO_PIN_7}, {GPIOA, GPIO_PIN_6}, {GPIOA, GPIO_PIN_5}
};
int showNum[][10] = {
// 第0位留空,1-7位控制灯管亮灭,8位控制小数点亮灭。可以根据自己的设计自行绘图
{0, 1, 1, 1, 1, 1, 1, 0, 1},// 0
{0, 0, 1, 1, 0, 0, 0, 0, 1},// 1
{0, 1, 1, 0, 1, 1, 0, 1, 1},// 2
{0, 1, 1, 1, 1, 0, 0, 1, 1},// 3
{0, 0, 1, 1, 0, 0, 1, 1, 1},// 4
{0, 1, 0, 1, 1, 0, 1, 1, 1},// 5
{0, 1, 0, 1, 1, 1, 1, 1, 1},// 6
//7,8,9自己探索一下
};
定义了一个引脚的结构体方便后续书写,allPins数组是控制abcdefg灯管的,allPins数组中第一个属于空着的,记得加上。control数组是控制点亮哪个灯块的。上面两个数组都根据自己的情况定义即可。
main函数中的代码如下:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_LPUART1_UART_Init();
int nums[6] = {0, 1, 2, 3, 4, 5};
int size = 6;
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
for(int i = 0; i < size; i++) {
HAL_GPIO_WritePin(control[i].port, control[i].pin, GPIO_HIGH);
for(int j = 1; j <= 8; j++) {
HAL_GPIO_WritePin(allPins[j].port, allPins[j].pin, showNum[nums[i]][j] ? GPIO_LOW : GPIO_HIGH);
}
for(int j = 0; j < 1000; j++) {
__NOP();
}
HAL_GPIO_WritePin(control[i].port, control[i].pin, GPIO_LOW);
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
这里对__NOP();
函数进行一个解释:
这条语句的作用就是执行一条空指令nope
,占用一个主频分之一的时间。通过循环执行可以实现灵活的延时效果,相较于HAL_Delay(0)
函数可以将延时时间精度进一步提高而不仅限于1ms的精度。
上述代码完成的功能是实现六位数码管显示012345。显示原理:在每个瞬间同时只显示一个数字,但是通过快速的轮转营造出同时显示所有数字的效果。在轮转时对于每个数字需要有一定的持续时间,以保证电平切换不会有问题。
如果显示不出来可以把__NOP();换成HAL_Delay(0).。
三、ESP32点亮数码管
原理差不多,只需要更改一下即可。
#define Pin_1 15
#define Pin_2 2
#define Pin_3 0
#define Pin_a 4
#define Pin_f 16
#define Pin_4 17
#define Pin_5 5
#define Pin_d 12
#define Pin_h 14
#define Pin_e 27
#define Pin_c 26
#define Pin_6 25
#define Pin_g 33
#define Pin_b 32
#define Pin_NULL 23
//宏定义定义引脚
int allPins[20] = {
Pin_NULL, Pin_a, Pin_b, Pin_c, Pin_d, Pin_e, Pin_f, Pin_g, Pin_h,
};
int control[10] = {
Pin_1, Pin_2, Pin_3, Pin_4, Pin_5, Pin_6,
};
int showNum[][10] = {
{0, 1, 1, 1, 1, 1, 1, 0, 1},// 0
{0, 0, 1, 1, 0, 0, 0, 0, 1},// 1
{0, 1, 1, 0, 1, 1, 0, 1, 1},// 2
{0, 1, 1, 1, 1, 0, 0, 1, 1},// 3
{0, 0, 1, 1, 0, 0, 1, 1, 1},// 4
{0, 1, 0, 1, 1, 0, 1, 1, 1},// 5
{0, 1, 0, 1, 1, 1, 1, 1, 1},// 6
{0, 1, 1, 1, 0, 0, 0, 0, 1},// 7
{0, 1, 1, 1, 1, 1, 1, 1, 1},// 8
{0, 1, 1, 1, 0, 0, 1, 1, 1},// 9
};
#define DELAY_NOP 7200
void setup() {
for (int i = 1; i <= 8; i++) {
pinMode(allPins[i], OUTPUT);
digitalWrite(allPins[i], LOW);
}
for (int i = 0; i < 6; i++) {
pinMode(control[i], OUTPUT);
digitalWrite(control[i], LOW);
}
}
// put your setup code here, to run once:
int size = 6;
int nums[] = {0, 0, 0, 1, 0, 0};
int t = 0;
int flag = 166;
void loop() {
for (char i = 0; i < size; i++) {
if (flag == 0) {
flag = 1;
t += 1;
int tmp = t;
for (int j = 0; j < 6; j++) {
nums[5 - j] = tmp > 0 ? tmp % 10 : 0;
tmp /= 10;
}
}
flag--;
digitalWrite(control[i], HIGH);
for (char j = 1; j <= 8; j++) {
digitalWrite(allPins[j], showNum[nums[i]][j] ? LOW : HIGH);
}
delay(1);
digitalWrite(control[i], LOW);
}
}
上述代码的功能是实现一个不太标准的计时器,不太标准是因为本来应该1ms更新一次时间,但是由于显示的限制更新时间不太准确。如果有更好的解决办法麻烦告诉我TT。
前三位是秒,后三位是毫秒,实现一个毫秒级别的计时器。
四、工程源码
我写的是STM32G474RET6的代码,这个板子能直接烧录,其他的需要自己修改一下。具体引脚连接请见cubemx文件。
老样子上传到百度网盘上面了,ESP32的工程直接粘代码就可以。
通过百度网盘分享的文件:SHUMAGUAN.zip
提取码:6666