最近拿到了,只要用6个脚就能驱动
具体来说,原理是,两个脚一个脚为正,一个脚为负,就能点亮一段数码管。其他脚保持关闭状态
这样理论上可以实现6x5=30种点亮方式。3位数码管每位8个管脚加上一个小数点,刚好是27个灯
一次点亮一个灯,然后通过循环里一直切换,实现完整的显示
这里给一个数据手册的示意图
不过具体的引脚排列每个厂家都不一样,可以用万用表测出来。用红笔和黑笔接两个脚,某个灯管就亮了
管脚命名参考:
显示效果:
例程
使用方法:
#include"Display_seg.h"intmain(){SEG_Init();// 初始化引脚和变量while(1){SEG_Update();// 刷新显示SEG_Display_Num(DIGIT_1,1);// 第一位显示1SEG_Display_Num(DIGIT_2,2);SEG_Display_Num(DIGIT_3,3);}}适配方法
注意每个单片机的函数不一样
把#include "sc.h"换成自己单片机的头文件#define SEG1_PIN RB6 // 引脚1: PB6 ...
引脚改为自己的引脚代码#define SEG1_INPUT() TRISB6 = 1 ...
引脚方向改为自己的引脚方向设置函数
灯序不一样的还要改一下这里的排序static const SegMap seg_map[] = {{2, 3, SEG_A, DIGIT_1}, ...
**{2,3…**表示电流方向是2->3时,亮第一个管脚
代码
Display_seg.h
#ifndef__SEG_DISPLAY_H#define__SEG_DISPLAY_H#include"sc.h"//---------------------------------// 用户自定义 数码管引脚//---------------------------------// 引脚定义(根据您的接线)#defineSEG1_PINRB6// 引脚1: PB6#defineSEG2_PINRB5// 引脚2: PB5#defineSEG3_PINRB4// 引脚3: PB4#defineSEG4_PINRA3// 引脚4: PA3#defineSEG5_PINRA4// 引脚5: PA4#defineSEG6_PINRA5// 引脚6: PA5// 引脚方向#defineSEG1_INPUT()TRISB6=1#defineSEG2_INPUT()TRISB5=1#defineSEG3_INPUT()TRISB4=1#defineSEG4_INPUT()TRISA3=1#defineSEG5_INPUT()TRISA4=1#defineSEG6_INPUT()TRISA5=1#defineSEG1_OUTPUT()TRISB6=0#defineSEG2_OUTPUT()TRISB5=0#defineSEG3_OUTPUT()TRISB4=0#defineSEG4_OUTPUT()TRISA3=0#defineSEG5_OUTPUT()TRISA4=0#defineSEG6_OUTPUT()TRISA5=0//---------------------------------// 函数声明voidSEG_Init(void);// 初始化数码管voidSEG_Clear(void);// 清空显示// 显示一位数字// 变量:(数码管,数字)voidSEG_Display_Num(unsignedchardigit,unsignedcharnum);// 显示一个小数点voidSEG_Display_DP(unsignedchardigit,unsignedcharstate);// 刷新屏幕(需要在循环调用!!!重要)voidSEG_Update(void);// 使用示例:/* int main() { SEG_Init(); while(1) { SEG_Update();// 刷新显示 SEG_Display_Num(DIGIT_1, 1); // 第一位显示1 SEG_Display_Num(DIGIT_2, 2); SEG_Display_Num(DIGIT_3, 3); } } */// 数码管编号#defineDIGIT_10#defineDIGIT_21#defineDIGIT_32// 段码定义 (dp,g,f,e,d,c,b,a)#defineSEG_A0x01#defineSEG_B0x02#defineSEG_C0x04#defineSEG_D0x08#defineSEG_E0x10#defineSEG_F0x20#defineSEG_G0x40#defineSEG_DP0x80// 数码管字段(A到G)// AAAAA// F B// F B// GGGGG// E C// E C// DDDDD DP//// 数字0-9的字库constunsignedcharseg_code[]={SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F,// 0SEG_B|SEG_C,// 1SEG_A|SEG_B|SEG_G|SEG_E|SEG_D,// 2SEG_A|SEG_B|SEG_G|SEG_C|SEG_D,// 3SEG_F|SEG_G|SEG_B|SEG_C,// 4SEG_A|SEG_F|SEG_G|SEG_C|SEG_D,// 5SEG_A|SEG_F|SEG_G|SEG_E|SEG_C|SEG_D,// 6SEG_A|SEG_B|SEG_C,// 7SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G,// 8SEG_A|SEG_B|SEG_C|SEG_D|SEG_F|SEG_G,// 9SEG_A|SEG_B|SEG_C|SEG_E|SEG_F|SEG_G,// A [10]SEG_C|SEG_D|SEG_E|SEG_F|SEG_G,// b [11]SEG_A|SEG_D|SEG_E|SEG_F,// C [12]SEG_B|SEG_C|SEG_D|SEG_E|SEG_G,// d [13]SEG_A|SEG_D|SEG_E|SEG_F|SEG_G,// E [14]SEG_A|SEG_E|SEG_F|SEG_G,// F [15]SEG_B|SEG_C|SEG_E|SEG_F|SEG_G,// H [16]SEG_D|SEG_E|SEG_F,// L [17]SEG_A|SEG_B|SEG_E|SEG_F|SEG_G,// P [18]SEG_E|SEG_G,// r [19]SEG_G// - [20]};#defineSEG_CODE_SIZE(sizeof(seg_code)/sizeof(unsignedchar))#endifDisplay_seg.c
#include"Display_seg.h"#include<stdint.h>// 显示缓冲区(3位数码管)staticunsignedcharseg_buffer[3]={0,0,0};// 当前扫描的数码管staticunsignedcharcurrent_digit=0;// 引脚配置表// 格式: {阳极引脚, 阴极引脚, 段码位}// 需要根据实际数码管内部连接关系填写typedefstruct{unsignedcharanode;// 高电平引脚 (1-6)unsignedcharcathode;// 低电平引脚 (1-6)unsignedcharsegment;// 段码unsignedchardigit;// 数码管位 (0-2)}SegMap;// 这里需要根据实际接线测试并修改// 每个LED由两个引脚控制:一个阳极,一个阴极staticconstSegMap seg_map[]={// 第1位数码管{2,3,SEG_A,DIGIT_1},// A1: PB6->PB5{2,4,SEG_B,DIGIT_1},// B1: PB5->PB4{5,2,SEG_C,DIGIT_1},// C1: PB4->PA3{2,6,SEG_D,DIGIT_1},// D1: PA3->PA4{2,5,SEG_E,DIGIT_1},// E1: PA4->PA5{3,2,SEG_F,DIGIT_1},// F1: PA5->PB6{4,2,SEG_G,DIGIT_1},// G1: PB6->PB4{2,1,SEG_DP,DIGIT_1},// DP1: PB5->PA3// 第2位数码管{5,4,SEG_A,DIGIT_2},// A2: PB4->PA4{3,5,SEG_B,DIGIT_2},// B2: PA3->PA5{4,5,SEG_C,DIGIT_2},// C2: PA4->PB6{3,4,SEG_D,DIGIT_2},// D2: PA5->PB5{6,3,SEG_E,DIGIT_2},// E2: PB6->PA3{4,3,SEG_F,DIGIT_2},// F2: PB5->PA4{5,3,SEG_G,DIGIT_2},// G2: PB4->PA5{3,1,SEG_DP,DIGIT_2},// DP2: PA3->PB6// 第3位数码管{1,6,SEG_A,DIGIT_3},// A3: PA4->PB5{3,6,SEG_B,DIGIT_3},// B3: PA5->PB4{5,6,SEG_C,DIGIT_3},// C3: PB6->PA4{6,4,SEG_D,DIGIT_3},// D3: PB5->PA5{4,6,SEG_E,DIGIT_3},// E3: PB4->PB6{6,5,SEG_F,DIGIT_3},// F3: PA3->PB5{1,5,SEG_G,DIGIT_3},// G3: PA4->PB4{6,4,SEG_DP,DIGIT_3},// DP3: PA5->PA3};#defineSEG_MAP_SIZE(sizeof(seg_map)/sizeof(SegMap))// 初始化数码管voidSEG_Init(void){// 初始化所有引脚为输入高阻态TRISA|=0b00111000;// RB4,RB5,RB6 -> 输入WPUA|=0b00111000;// 上拉电阻TRISB|=0b01110000;// RB4,RB5,RB6 -> 输入WPUB|=0b01110000;// 上拉电阻// 初始化显示缓冲区seg_buffer[0]=0;seg_buffer[1]=0;seg_buffer[2]=0;current_digit=0;}// 清除显示voidSEG_Clear(void){// 初始化所有引脚为输入高阻态TRISA|=0b00111000;// RB4,RB5,RB6 -> 输入WPUA|=0b00111000;// 上拉电阻TRISB|=0b01110000;// RB4,RB5,RB6 -> 输入WPUB|=0b01110000;// 上拉电阻}// 操控6个引脚状态 (0:低电平, 1:高电平, 其他:高阻态)staticvoidset_pin(unsignedcharpin,unsignedcharstate){switch(pin){case1:if(state==1){SEG1_OUTPUT();SEG1_PIN=1;}elseif(state==0){SEG1_OUTPUT();SEG1_PIN=0;}else{// 高阻态SEG1_INPUT();SEG1_PIN=0;}break;case2:if(state==1){SEG2_OUTPUT();SEG2_PIN=1;}elseif(state==0){SEG2_OUTPUT();SEG2_PIN=0;}else{SEG2_INPUT();SEG2_PIN=0;}break;case3:if(state==1){SEG3_OUTPUT();SEG3_PIN=1;}elseif(state==0){SEG3_OUTPUT();SEG3_PIN=0;}else{SEG3_INPUT();SEG3_PIN=0;}break;case4:if(state==1){SEG4_OUTPUT();SEG4_PIN=1;}elseif(state==0){SEG4_OUTPUT();SEG4_PIN=0;}else{SEG4_INPUT();SEG4_PIN=0;}break;case5:if(state==1){SEG5_OUTPUT();SEG5_PIN=1;}elseif(state==0){SEG5_OUTPUT();SEG5_PIN=0;}else{SEG5_INPUT();SEG5_PIN=0;}break;case6:if(state==1){SEG6_OUTPUT();SEG6_PIN=1;}elseif(state==0){SEG6_OUTPUT();SEG6_PIN=0;}else{SEG6_INPUT();SEG6_PIN=0;}break;}}// 显示一位数字voidSEG_Display_Num(unsignedchardigit,unsignedcharnum){if(digit<3&&num<10){seg_buffer[digit]=seg_code[num];}}// 显示一个小数点voidSEG_Display_DP(unsignedchardigit,unsignedcharstate){if(digit<3){if(state==1){seg_buffer[digit]|=SEG_DP;}else{seg_buffer[digit]&=~SEG_DP;}}}// 更新显示(需要在循环调用才能显示 !!!)voidSEG_Update(void){// 一次更新一位数码管staticunsignedcharseg_num=0;constSegMap*map=&seg_map[seg_num];// 检查该段是否需要点亮if(seg_buffer[map->digit]&map->segment){// 点亮这个LEDSEG_Clear();set_pin(map->anode,1);// 阳极set_pin(map->cathode,0);// 阴极}else{// LED不需要时关闭 //注意:不加关闭会导致显示亮度不均SEG_Clear();}seg_num=(seg_num+1)%SEG_MAP_SIZE;}