newlandmark

Using Charlie multiplexing method to drive digital tube, the most elegant bar clock

 
Overview

Preface

Digital tube drive circuit: Charlie multiplexing method

8 IOs drive an 8-bit 7-segment digital tube, and the circuit is very similar to the key-conflict-free circuit of most mechanical keyboards . So the names are consistent.

The digital tube is integrated on the PCB, and the light transmission is softened through 3D printing parts, and the integrated display of the shell is more beautiful.

In the later stage, we tried to transplant the program of foot-to-foot compatible chip. At present, we first developed the sponsor of this event: Hangshun HK32F030M.

Let’s complain about the location of the programming port and the multiplexing of hardware I2C. You cannot use I2C while debugging.

Circuit principle description

This is the schematic diagram of using 3 ios to drive 6 LEDs using Charlie multiplexing method.

image.png

Assume that P1 is high, P3 is low, and P2 is high resistance. LED6 is on at this time. Although LED1 and LED3 have forward voltage in series, due to the clamping of LED6, the voltage is not enough to turn on at the same time.

image.png

If P1 is high, P2 and P3 are both low, then both LED1 and LED6 are on, but the brightness is not as bright as the above state, because the current of both LEDs flows through the P3 resistor, and the voltage division of the P3 resistor increases.

image.png

Therefore, a diode is connected in parallel to each current-limiting resistor, and the one-way conductivity is used to make the voltage division at both ends of the resistor consistent in a specific current direction, so that the LEDs that light up at the same time have the same brightness.

image.png

Core algorithm description

It’s not that my code is not open source, but that the code is released, even if 100 people download it. However, 80 people couldn't understand it.

Then I might as well just list the special algorithms and explain them with pictures and texts so that more people can understand them.

You can take a look at the power supply project of my GD32 cup . Although the final function was not successful, it was often collected and cloned by people every now and then, but no one liked it [PS: You should like all three. Your support is my motivation for updating]. If you have anything you want to see about the algorithm, please mention it in the comments section. I will update later when I have time.

ADC oversampling:

According to the technical documentation, the effective accuracy of the ADC of HK32F030M is 8 bits. If the temperature is to be displayed to 1 digit after the decimal point, an ADC of at least 12 bits is required.

What to do about this?

At this time, supersampling technology can be used.

In the first step, the ADC is set to continuous conversion, and the EOC conversion is completed and interrupted.

void ADC_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    GPIO_InitStructure.GPIO_Pin = GPIO_ADC_PIN ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GOIO_ADC_PORT, &GPIO_InitStructure);
    GPIO_PinAFConfig(GOIO_ADC_PORT,GPIO_PinSource6,GPIO_AF_7);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC ,ENABLE);

    ADC_DeInit(ADC1);
    ADC_StructInit(&ADC_InitStructure);

    ADC_ClockModeConfig(ADC1,ADC_ClockMode_SynClkDiv4);//系统时钟4分频,8M

    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
    ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;//向后扫描
    ADC_Init(ADC1,&ADC_InitStructure);
    /* ADC1 regular channels configuration */ 
    ADC_ChannelConfig(ADC1, ADC_Channel_1 , ADC_SampleTime_239_5Cycles);

    /* Enable EOC interrupt */
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);//转换结束中断使能

    /* Configure and enable ADC1 interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = ADC1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    ADC_GetCalibrationFactor(ADC1);//ADC校准

    /* Enable ADC1 */
    ADC_Cmd(ADC1, ENABLE);

    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY)); 
    ADC_StartOfConversion(ADC1);
}

The second step is to accumulate the values ​​read back by the ADC in the interrupt (since the average is required later, it is better to add it up first).

Here, since the keys and the thermistor share the same ADC, in order to ensure normal key scanning, the refresh rate is set to a number slightly larger than 1000Hz.

extern uint16_t ntc_data_13b[2];
void ADC1_COMP_IRQHandler(void)
{
    static uint8_t i=0;
    if(ADC_GetITStatus(ADC1, ADC_IT_EOC) != RESET)
    {
        ntc_data_13b[0]+=ADC_GetConversionValue(ADC1)>>4;//读取后自动清除EOC标志位
        i++;
        if(i>=32)//32分频,1041.6Hz
        {
            i=0;
            ntc_data_13b[1]=ntc_data_13b[0];//存入二缓
            ntc_data_13b[0]=0;//一缓清零
        }
    }
}

Digital tube moving up and down animation:

There are a lot of animation special effects. Here is a simpler one, using downward movement as an example.

image.png

The picture above shows the process of moving down. There is only one step to extract the repeated parts (the same goes for moving up).

#define digital_a 0x01
#define digital_b 0x02
#define digital_c 0x04
#define digital_d 0x08
#define digital_e 0x10
#define digital_f 0x20
#define digital_g 0x40

uint8_t digital_putdown(uint8_t dat)
{
    uint8_t temp=0;
    temp|=(dat&digital_g)?digital_d:0;//G赋值到D
    temp|=(dat&digital_a)?digital_g:0;//A赋值到G
    temp|=(dat&digital_b)?digital_c:0;//B赋值到C
    temp|=(dat&digital_f)?digital_e:0;//F赋值到E
    return temp;//其余没赋值的数据丢弃
}

Travel time error calibration:

First of all, many people have given inaccurate feedback on this DS1302. In fact, there is a trick:

You can refer to this website: http://www.51hei.com/bbs/dpj-177015-1.html

The code below adjusts the time.

//输入最小数值-86400
void time_adjust(int32_t sec)
{
    uint8_t time_temp[7];
    uint8_t i;
    for(i=0;i<7;i++)
        time_temp[i]=bcd2hex(*((uint8_t *)&time_data+i));

    if(sec<0)//直接借一天做减法
    {
        sec+=86400;
        time_temp[5]--;//星期是从1到7,不担心溢出
    }

    time_temp[0]+=sec%60;
    if(time_temp[0]>=60)
    { 
        time_temp[1]+=time_temp[0]/60;
        time_temp[0]%=60;
    }
    time_temp[1]+=sec%3600/60;
    if(time_temp[1]>=60)
    {
        time_temp[2]+=time_temp[1]/60;
        time_temp[1]%=60;
    }
    time_temp[2]+=sec/3600; 
    if(time_temp[2]>=24)
    {
        time_temp[5]+=time_temp[2]/24;
        time_temp[2]%=24;

        time_temp[5]%=7;
        time_temp[5]=time_temp[5]?time_temp[5]:7;//将零偏移到7
    }

    for(i=0;i<7;i++)
        *((uint8_t *)&time_data+i)=hex2bcd(time_temp[i]);
}

Since I don’t have year, month and day here, only week, it’s a little easier. There is no need to consider more bases.

As in the above website, choose a quiet time at night to calibrate. Of course, there is a chance that the alarm will be skipped during calibration. But who would set the midnight bell?

参考设计图片
×
 
 
Search Datasheet?

Supported by EEWorld Datasheet

Forum More
Update:2024-11-14 23:46:12

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号