doorxp

Blog

5 针 188 LED显示屏 带风扇和雪花

原理

截屏2025-05-16 15.49.06.png截屏2025-05-16 15.49.06.png


CH32V203 驱动代码

#include "LED188Display.h"
#include "SysTick.h"
#include "Utils.h"
#include <strings.h>
#include <assert.h>

const GPIOSpeed_TypeDef GPIO_Speed = GPIO_Speed_2MHz;

typedef struct _SEGPOINT{
GPIO_TypeDef* PORT;
    uint16_t PIN;
} SEGPOINT;

#define DPA {GPIOB,GPIO_Pin_3}
#define DPB {GPIOB,GPIO_Pin_4}
#define DPC {GPIOB,GPIO_Pin_5}
#define DPD {GPIOB,GPIO_Pin_6}
#define DPE {GPIOB,GPIO_Pin_7}

//显示五个针脚
const SEGPOINT POINTS[] = {DPA, DPB, DPC, DPD, DPE};

//定义显示表,5针,可以显示 5*4=20 种状态 i=j 不能用
u8 showTable[5][5] = {0};



const u16 LEDPins = POINTS[0].PIN | POINTS[1].PIN | POINTS[2].PIN | POINTS[3].PIN | POINTS[4].PIN;



volatile static uint8_t value = 0;
volatile static uint8_t k1 = 0;
volatile static uint8_t k2 = 0;
volatile static u8 needUpdate = 0;
volatile static uint8_t blink = 0;

static uint32_t _counter = 0;
void updateTable(uint8_t num, uint8_t fan, uint8_t zhilen);

void display(void){
// uint8_t num = value;
    if(blink){
        _counter++;
        if(_counter > 55){
            _counter = 0;
        }
    }
    else{
        _counter = 0;
    }
    
    if(needUpdate){
        needUpdate = 0;
        updateTable(value, k1, k2);
    }

    for(u8 i = 0; i < 5; i++){
        //个位闪烁时熄灭状态
        if(_counter >= 30 && i == 0) continue;
        
        //判断第i个PIN 为低电平时,有需要显示me v为0 不需要显示, 其他需要显示 
        u8 v = showTable[i][1] | showTable[i][2] | showTable[i][3] | showTable[i][4];
        if(_counter < 30){ v |= showTable[i][0]; } //第 0 位闪烁时, 不亮 LED 不需要参加判断
    
        if(v){
            //第 i个引脚为低电平时, 其他4 个引脚 有至少一个 段要亮, 所以需要设置第 i 个引脚为低电平
            GPIO_ResetBits(POINTS[i].PORT, POINTS[i].PIN);
            
            u8 highPins = 0;//记录需要高电平的引脚
            //判断其他 4 个引脚 是否有需要显示的段,需要就要设置为高电平
            for(u8 j = 0; j < 5; j++){
                if(j == i || showTable[i][j] == 0)continue;
                if((j == 0 || i == 0) && _counter >= 30) continue;
                //如果 i 和 j 都不是 0,或者 _counter < 30,才设置 highPins
                if((i != 0 && j != 0) || _counter < 30){
                    highPins |= POINTS[j].PIN;
                }
            }
            //设置highPins为高电平
            GPIO_CONFIG(POINTS[i].PORT, highPins, GPIO_Mode_Out_PP, GPIO_Speed);
            GPIO_SetBits(POINTS[i].PORT, highPins);
            //延时
            Delay_US(50);
            //设置highPins为高阻状态, 这些 PIN 已经是高电平了.一行代码搞定 
            GPIO_CONFIG(GPIOB, highPins, GPIO_Mode_Out_OD, GPIO_Speed);
            //恢复低电平PIN为高阻状态
            GPIO_SetBits(POINTS[i].PORT, POINTS[i].PIN);
        }
    }

}

//根据段码表得到,不能修改
#define FAN_SEG_CODE 0x02
#define COOL_SEG_CODE 0x04

/* 0-9 的段码, 0x01 代表 风扇, 0x02 代表制冷 */
u8 segmentCodes[] = {0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0x7F, 0x7B, FAN_SEG_CODE, COOL_SEG_CODE};


typedef struct{
    u8 pH;
    u8 pL;
}AK;

#define _NCAK {0,0} //没有用的 AK
const AK AKTable[3][7] = {
{{4, 0}, {3, 0}, {0, 3}, {2, 0}, {0, 2}, {1, 0}, {0, 1}},//个位
{{4, 3}, {4, 2}, {4, 1}, {3, 1}, {3, 2}, {2, 1}, {1, 2}},//十位
{_NCAK, {2, 4}, {1, 4}, _NCAK, {1, 3}, {2, 3}, _NCAK},//百位和风扇图标,制冷图标
};

void getTableIndex(u8 wei, u8 mask, u8* pH, u8* pL) {
    u8 bit = __builtin_ctz(mask);
    // u8 bit;
    // __asm__("ctz %0, %1" : "=r"(bit) : "r"(mask));
    AK ak = AKTable[wei][bit];
    *pH = ak.pH;
    *pL = ak.pL;
}


void updateTable(uint8_t num, uint8_t fan, uint8_t zhilen){
    bzero(showTable, sizeof(showTable));
    u8 pH = 0;//高位PIN在POINTS中的索引
    u8 pL = 0;//低位PIN在POINTS中的索引
    u8 code = 0;//当前位段码
    u8 value = num;
    //个,十,百位, 风扇, 制冷图标编码在百位F2,E2中
    
    for(u8 j = 0; j < 3; j++){
        code = segmentCodes[value % 10];
        u8 mask = 1;
        for(u8 i = 0; i < 7; i++){
            u8 v = code & mask;
            if(v){
                getTableIndex(j, mask, &pH, &pL);
                showTable[pL][pH] = mask;
            }
            mask <<= 1;
        }
        value /= 10;
        if(value <= 0) break;
    }

    if(fan){
        getTableIndex(2, FAN_SEG_CODE, &pH, &pL);
        showTable[pL][pH] = FAN_SEG_CODE;
    }
    if(zhilen){
        getTableIndex(2, COOL_SEG_CODE, &pH, &pL);
        showTable[pL][pH] = COOL_SEG_CODE;
    }
}

void LED188_Display(uint8_t num, uint8_t fan, uint8_t zhilen, uint8_t b){
    if(num > 199){ num = 199; }
    if(value == num && fan == k1 && zhilen == k2 && blink == b)return;
    value = num;
    k1 = fan;
    k2 = zhilen;
    blink = b;
    needUpdate = 1;
}


发表评论:

«   2025年5月   »
1234
567891011
12131415161718
19202122232425
262728293031
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
搜索
最新留言

    Powered By Z-BlogPHP 1.5.1 Zero

    Copyright doorxp.com Rights Reserved.