找回密码
 立即注册
楼主: f278457546

冲哥的8051u学习

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2026-05-01 03:00:05
已绑定手机

2

主题

54

回帖

144

积分

注册会员

积分
144
发表于 3 天前 | 显示全部楼层

可以单独现实的2x4数码管

#include "digital_display_tube.h"
//74hc595  先发高位再发低位,第一个字节是断码,第二个字节是位选
//sck上升沿移位data,sck低电平时准备data,8个data后rck输出

typedef struct
{
    u8 num;
    u8 point;
} digital_display_tube;



u8 code smgduan[18] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
                       0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x40}; // 0-f, 负号
u8 code wei[8]={127,191,223,239,247,251,253,254};
digital_display_tube  digital_tube[8];
u8 display1_len = 0;
u8 display2_len = 0;
bit digital_tube_on = 0; // data管显示开关
bit display_mode = 0;    // 显示模式:0单参数,1双参数
void digital_display_tube_init(void)
{
    u8 i;
    for (i = 0; i < 8; i++)
    {
        digital_tube[i].num = i;
        digital_tube[i].point = 0; // 无小shu点
    }
    display1_len=8;
    digital_display_on();
}
void digital_display_on(void)
{
    digital_tube_on = 1;
}

void digital_display_off(void)
{
    digital_tube_on = 0;
}





void hc595_send_char(u8 duan){
u8 i;
    RCK=0;
    for(i=0;i<8;i++)
    {
     SCK=0;
        DAT= (duan&0x80 ) ?1:0 ;
        //printf("num: d%   send: %d  dat: %d \r\n",(int)i,(int)duan,(int)DAT);
        duan<<=1;
        SCK=0;
        SCK=1;  
    }
    RCK=1;
    RCK=0;
}
void digital_display_tube_refresh(){
  u8 i,w;

    if (digital_tube_on == 0)
        return;
  if (display_mode == 0) // 单参shu模式
    {
        for (i = 0; i < display1_len; i++)
        {   
             w=smgduan[digital_tube[i].num] + (digital_tube[i].point ? 0x80 : 0x00);
            hc595_send_char(w);
            hc595_send_char(wei[7-i-display1_len]);
            delay_ms(refresh_speed);
        }
    }
  
  
    else // 双参数模式
    {
        //printf("双参数模式刷新 \n");
        for (i = 0; i < display1_len; i++)
        {
            w=smgduan[digital_tube[7-i].num] + (digital_tube[7-i].point ? 0x80 : 0x00);
            hc595_send_char(w);
            hc595_send_char(wei[i]);
            delay_ms(refresh_speed);
        }
        for (i = 0; i < display2_len; i++)
        {
             w=smgduan[digital_tube[3-i].num] + (digital_tube[3-i].point ? 0x80 : 0x00);
            hc595_send_char(w);
            hc595_send_char(wei[i+4]);
            delay_ms(refresh_speed);
        }

    }
  
  
  
}


void digital_display_tube_display(u32 num1, u32 num2)
{
    u8 str[8] = {0xff}, i;

    if (num1 != 0)
    {
        display_mode = 0; // 单参数模式
        sprintf(str, "%lu", num1);
        display1_len = strlen(str);
        if (display1_len > 8)
        {
            display1_len = 8; // 超过8位只显示前8位
        }
        for (i = 0; i < 8; i++)
        {
            str[i] = str[i] == ' ' ? 0xff : str[i] - '0'; // 将空格转换为0xff,数字字符转换为对应的数字
            digital_tube[i].num = str[i] & 0x0f;          // 取数字部分
        }
        display2_len = 0; // 单参数模式时,第二个数长度为0
    }

    if (num2 != 0)
    {
        display_mode = 1; // 双参数模式
        sprintf(str, "%lu", num2);
        display2_len = strlen(str);
        if (display2_len > 4)
        {
            display2_len = 4; // 超过4位只显示前4位
        }
        for (i = 0; i < 4; i++)
        {
            str[i] = str[i] == ' ' ? 0xff : str[i] - '0'; // 将空格转换为0xff,数字字符转换为对应的数字
            digital_tube[4 + i].num = str[i] & 0x0f;      // 取数字部分
        }
    }
    // for (i = 0; i < 8; i++)
    // {
    //     printf("num1:%d ; num2:%d  -- digital_tube[%d].num = %02x \n", (int)num1, (int)num2, (int)i, (int)digital_tube[i].num);
    // }
}



// 显示时钟函数:hour 小时(0~23),min 分钟(0~59)
// 显示格式:8位数码管 →  时 时 . 分 分 (中间小数点作为冒号)
void show_time(u8 hour, u8 min)
{
    u8 h1, h2;   // 小时十位、个位
    u8 m1, m2;   // 分钟十位、个位
    u8 i;

    // 关闭显示,防止刷新冲突
    digital_display_off();

    // 拆分小时
    h1 = hour / 10;  // 小时十位
    h2 = hour % 10;  // 小时个位

    // 拆分分钟
    m1 = min / 10;   // 分钟十位
    m2 = min % 10;   // 分钟个位

    // 清空所有数码管
    for(i=0; i<8; i++)
    {
        digital_tube[i].num = 0xff;    // 不亮
        digital_tube[i].point = 0;
    }

    // ====================== 8位数码管显示时钟 ======================
    // 第0位:小时十位
    digital_tube[0].num = h1;
    digital_tube[0].point = 0;

    // 第1位:小时个位
    digital_tube[1].num = h2;
    digital_tube[1].point = 1;  // 打开小数点 → 模拟冒号:

    // 第2位:分钟十位
    digital_tube[2].num = m1;
    digital_tube[2].point = 0;

    // 第3位:分钟个位
    digital_tube[3].num = m2;
    digital_tube[3].point = 0;
    // ==============================================================

    // 设置显示长度(只显示前4位)
    display1_len = 4;
    display2_len = 0;
    display_mode = 0;  // 单参数模式

    // 打开显示
    digital_display_on();
}
#ifndef DIGITAL_DISPLAY_TUBE_H
#define DIGITAL_DISPLAY_TUBE_H

#include "config.h"

#define SCK P32
#define DAT P34
#define RCK P35




//#define digital_tube_segment_selection  P0  // data线
//#define digital_tube_position_selection P2  // data管位选 (digital_tube_position_selection & 0xe3) | (i << 2);
#define refresh_speed                   3 // 刷新速度

void digital_display_tube_init(void);
void digital_display_on(void);
void digital_display_off(void);


void show_time(u8 hour, u8 min);
void digital_display_tube_display(u32 num1, u32 num2);
void digital_display_tube_refresh(); //  刷新data管显示
#endif                             
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:9
  • 最近打卡:2026-05-01 03:00:05
已绑定手机

2

主题

54

回帖

144

积分

注册会员

积分
144
发表于 3 天前 | 显示全部楼层

矩阵键盘

#include "key_matrix.h"

u8 key_matrix_scan(u8 mode)
{
static u8 key_mode = 1;
u8 row, col;
KEY_MATRIX = 0x0f; // 设置行为输入,列为输出
if (mode)
{
key_mode = 1;
}
//printf("key_matrix_scan: %d \r\n",(int)(KEY_MATRIX&0x0f));
if (key_mode == 1 && (KEY_MATRIX&0x0f)!= 0x0f)
{
delay_ms(debounce_time); // 防抖延时
key_mode = 0;
switch (KEY_MATRIX&0x0f)
{
case 14:
col = 1;
break;
case 13:
col = 2;
break;
case 11:
col = 3;
break;
case 7:
col = 4;
break;
default:
col = 0;
}
// printf("Key matrix col: %d\n", (int)(KEY_MATRIX&0x0f));
KEY_MATRIX = 0xc0; // 设置行为输出,列为输入
delay_ms(3);
row = KEY_MATRIX >> 6; // 读取行状态
switch (row)
{
case 2:
row = 1;
break;
case 1:
row = 2;
break;
default:
row = 0;
}
//printf("Key matrix row: %d\n", (int)row);
if (row == 0 || col == 0)
{
return 0;
}
// printf("Key matrix key: %d\n", (int)((row-1)*4 + col));
return (row-1)*4 + col; // 返回按键编号
}
else if (key_mode == 0 && KEY_MATRIX == 0x0f)
{
key_mode = 1;
}
return 0;
}
void key_matrix_handler()
{
switch (key_matrix_scan(0))
{
case 1:
printf("K 0 \n");
break;
case 2:
printf("K 1 \n");
break;
case 3:
printf("K 2 \n");
break;
case 4:
printf("K 3 \n");
break;
case 5:
printf("K 4 \n");
break;
case 6:
printf("K 5 \n");
break;
case 7:
printf("K 6 \n");
break;
case 8:
printf("K 7 \n");
break;
case 9:
printf("K 8 \n");
break;

}

}

#ifndef KEY_MATRIX_H
#define KEY_MATRIX_H
#include "config.h"

// pin define
#define KEY_MATRIX P0
#define debounce_time 10 // 防抖延时20us
u8 key_matrix_scan(u8 mode); // 线翻转方式 mode: 0-单次扫描,1-连续扫描
void key_matrix_handler();
#endif

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-5-1 10:29 , Processed in 0.108606 second(s), 49 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表