LCD1602显示的时钟秒的个位到十位跳跃出现了问题

基于stm32用LCD1602显示时钟,但是在秒的个位向十位跳转的时候 十位总是会提前一位跳转。比如:01 02 03 04
05 06 07 08 19 10 11 12....这样
怎么调才能正常地在节点跳转呢?
变成正常的08 09 10 11...这样子跳
问题代码如下:

main.c

#include "delay.h"
#include "LCDall.h"

int main()
{
    Systick_init();
    InitLCD();
    
    u32 A;
    u32 B;
    u32 C;
    u32 D;
    u32 E;
    u32 F;
    u32 i=0;
    
    while(1)
    {
        
        
        A=i/3600/10;//时十
        B=i/3600%10;//时个
        
        C=i%3600/60/10;//分十
        D=i%3600/60%10;//分个
        
        E=i%3600%60/10;//秒十
        F=i%3600%60%10;//秒个
        
        
    
        i+=1;
        
        
        NUM (0,0,A);
        NUM (1,0,B);
        LCD_SHOW (2,0, ":",1 );
        NUM (3,0,C);
        NUM (4,0,D);
        LCD_SHOW (5,0, ":",1);
        NUM (6,0,E);
        NUM (7,0,F);
        
        if (A==2 && B==4)
        {
            i=0;
        }
        delay_ms(1000);
    
    }
    
}


delay.c

#include "delay.h"
#include "stm32f10x.h"                  // Device header
uint32_t delay_fac_us;
uint32_t delay_fac_ms;

void Systick_init(void)
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
    delay_fac_ms = SystemCoreClock / 8000;  
    delay_fac_us = SystemCoreClock / 8000000;     
}

void delay_ms(uint32_t i)
{
    uint32_t temp;
    SysTick->LOAD=delay_fac_ms*i;      //设置重装数值, 72MHZ时
    SysTick->CTRL=0X01;        //使能,减到零时无动作,采用外部时钟源
    SysTick->VAL=0;            //清零计数器
    do
    {
        temp=SysTick->CTRL;       
    }
    while((temp&0x01)&&(!(temp&(1<<16))));    //等待时间到达
    SysTick->CTRL=0;    //关闭计数器
    SysTick->VAL=0;        //清空计数器
}

void delay_us(uint32_t i)
{
    uint32_t temp;
    SysTick->LOAD=delay_fac_us*i;      //设置重装数值, 72MHZ时
    SysTick->CTRL=0X01;        //使能,减到零时无动作,采用外部时钟源
    SysTick->VAL=0;            //清零计数器
    do
    {
        temp=SysTick->CTRL;       
    }
    while((temp&0x01)&&(!(temp&(1<<16))));    //等待时间到达
    SysTick->CTRL=0;    //关闭计数器
    SysTick->VAL=0;        //清空计数器
}


delay.h


#ifndef _DELAY_H
#define _DELAY_H

#include "stm32f10x.h"


void Systick_init(void);
void delay_ms(uint32_t i);
void delay_us(uint32_t i);


#endif

LCDall.c

#include "LCDall.h"
#include "stm32f10x.h"                  // Device header
#include "delay.h"                  // Device header
#include "string.h "

//static uint8_t delay_fac_us=0;//延时倍乘数
//static uint8_t delay_fac_ms=0;//延时倍乘数

void LCD_WCO(uint8_t cmd)
{
    GPIOB->ODR=0x00FF;
    delay_ms(2);
    LCD_RS_LOW;
    LCD_RW_LOW;
    LCD_E_LOW;
    delay_us(1);
    LCD_E_HIGH;
    LCD1602_GPIO_PORT->ODR&=(cmd|0xFF00);
  LCD_E_LOW;
  delay_us(400);
}

void LED_WDA(uint8_t dat)
{
    GPIOB->ODR=0x00FF;
   delay_ms(2);
   LCD_RS_HIGH;
   LCD_RW_LOW;
   delay_us(30);
   LCD_E_HIGH;
   LCD1602_GPIO_PORT->ODR &=(dat|0xFF00);
   LCD_E_LOW;
   delay_us(400);
}



void LCD_SET(uint8_t x, uint8_t y)
{
   uint8_t addr;
 
   if (y == 0) //由输入的屏幕坐标计算显示RAM的地址
     addr=0x00 + x; //第一行字符地址从 0x00 起始
     else
     addr=0x40+ x; //第二行字符地址从 0x40 起始
   LCD_WCO(addr|0x80); //设置 RAM 地址
}

void LCD_SHOW(uint8_t x, uint8_t y, uint8_t *str, uint8_t len)
{
   LCD_SET(x, y); //设置起始地址
   while (len--) //连续写入len个字符数据
  {
     LED_WDA(*str++);
  }
 }


void LCDI0INIT(void)
{  
    RCC_APB2PeriphClockCmd(LCD1602_CLK,ENABLE);
    
   GPIO_InitTypeDef LCD1602_GPIOStruct;
   LCD1602_GPIOStruct.GPIO_Mode= GPIO_Mode_Out_PP;
   LCD1602_GPIOStruct.GPIO_Speed =GPIO_Speed_10MHz;
   LCD1602_GPIOStruct.GPIO_Pin=LCD1602_E |LCD1602_RS| LCD1602_RW;
   GPIO_Init(LCD1602_GPIO_PORT,&LCD1602_GPIOStruct);
   LCD1602_GPIOStruct.GPIO_Mode = GPIO_Mode_Out_OD;
   LCD1602_GPIOStruct.GPIO_Pin= DB0|DB1|DB2|DB3|DB4|DB5|DB6|DB7;
   GPIO_Init(LCD1602_GPIO_PORT,&LCD1602_GPIOStruct);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
    
   GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
     //GPIO_SetBits(GPIOB,GPIO_Pin_3) ;

}

void InitLCD()
{
LCDI0INIT(); //初始化LCD用到的GPIO
LCD_WCO(0x38);//设置为8位总线、2行显示、5×7点阵字体
delay_ms(1);
LCD_WCO(0x01);//清屏,归HOME位
delay_ms(1);
LCD_WCO(0x06);//数据输入为增量方式,显示内容不移动
delay_ms(1);
LCD_WCO(0x0c);//开显示,关闭光标,光标不闪烁
delay_ms(1);
}


void NUM(uint8_t x, uint8_t y, uint8_t num)
{
    LCD_SET(x,y);//设置起始地址
    LED_WDA(num+'0');
    //CHAR(x,y,num+'0'/*没有这个+'0'就不能显示数字*/);
}


LCDall.h


#ifndef _LCDALL_H
#define _LCDALL_H
#include "stm32f10x.h"
#include "delay.h"                  // Device header
#include "LCDall.h"

#define LCD_RS_LOW GPIO_ResetBits(LCD1602_GPIO_PORT, LCD1602_RS)
#define LCD_RS_HIGH GPIO_SetBits(LCD1602_GPIO_PORT, LCD1602_RS)
#define LCD_RW_LOW GPIO_ResetBits(LCD1602_GPIO_PORT, LCD1602_RW)
#define LCD_RW_HIGH GPIO_SetBits(LCD1602_GPIO_PORT, LCD1602_RW)
#define LCD_E_LOW GPIO_SetBits(LCD1602_GPIO_PORT, LCD1602_E)
#define LCD_E_HIGH GPIO_SetBits(LCD1602_GPIO_PORT, LCD1602_E)


#define LCD1602_CLK  RCC_APB2Periph_GPIOB
#define LCD1602_GPIO_PORT GPIOB

#define DB0               GPIO_Pin_0
#define DB1               GPIO_Pin_1
#define DB2               GPIO_Pin_2
#define DB3               GPIO_Pin_3
#define DB4               GPIO_Pin_4
#define DB5               GPIO_Pin_5
#define DB6               GPIO_Pin_6
#define DB7               GPIO_Pin_7

#define LCD1602_E GPIO_Pin_12 //定义使能引脚
#define LCD1602_RW GPIO_Pin_13//定义读写引脚
#define LCD1602_RS GPIO_Pin_14 //定义数据、命名引脚



void LCD_WCO(uint8_t cmd);
void LED_WDA(uint8_t dat);
void LCD_SET(uint8_t x, uint8_t y);
void LCD_SHOW(uint8_t x, uint8_t y, uint8_t *str, uint8_t len);
void LCDI0INIT(void);
void InitLCD();
void NUM(uint8_t x, uint8_t y, uint8_t num);
void CHAR(uint8_t x, uint8_t y, uint8_t dat);

static uint8_t delay_fac_us=0;//延时倍乘数
static uint8_t delay_fac_ms=0;//延时倍乘数


#endif

有熟悉这方面朋友嘛 麻烦大家帮我看一下吧

  • 这篇博客: STM8四线驱动LCD1602中的 4. delay.c 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • #include "delay.h"
    
    //ms级别延时
    void Delay_ms(uint16_t nCount)
    {
      while(nCount--)
      {
        Delay_us(1000);
      }
    }
    
    //us级别延时
    void Delay_us(uint16_t nCount)
    {
      nCount *= 2;
      while(--nCount);
    }