
 
问题描述:
航顺单片机 HK32F030MF4P6用数码管显示驱动TM1624问题描述。
- 航顺单片HK32F030MF4P6的PC3/PC4/PC5引脚分别连接数码管驱动TM1624的DIN/CLK/STB;
- 当单独使用HK32F030MF4P6单片机最小系统和TM1624数码管模块的时候部分最小系统板能驱动数码管正常显示,而有的最小系统板最需要修改系统时钟后才能驱动数码管显示(如下图所示);
- 当单片机和数码管驱动集成在一块电路板上时数码管不能正常显示;

问题原因: STM32 GPIO工作原理
GPIO端口8个输入/输出模式
typedef enum
{ GPIO_Mode_AIN = 0x0,//模拟输入
  GPIO_Mode_IN_FLOATING = 0x04,//浮空输入
  GPIO_Mode_IPD = 0x28,//下拉输入
  GPIO_Mode_IPU = 0x48,//上拉输入
  
  GPIO_Mode_Out_OD = 0x14,//开漏输出
  GPIO_Mode_Out_PP = 0x10, //推挽式输出
  GPIO_Mode_AF_OD = 0x1C,//开漏复用输出
  GPIO_Mode_AF_PP = 0x18//推挽复用输出
}GPIOMode_TypeDef;
GPIO端口7个寄存器:
 2 个32位配置寄存器(GPIOx_CRL,GPIOx_CRH)
 - 端口配置低位寄存器 GPIOx_CRL
 - 端口配置高位寄存器 GPIOx_CRH
 2 个32位数据寄存器(GPIOx_IDR和GPIOx_ODR)
 - 端口输入数据寄存器 GPIOx_IDR
 - 端口输出数据寄存器 GPIOx_ODR
 1 个32位置位/复位寄存器(GPIOx_BSRR)
 1 个16位复位寄存器(GPIOx_BRR)
 1 个32位锁定寄存器(GPIOx_LCKR)
解决方案:
用 GPIO_SetBits(GPIOC,GPIO_Pin_5); 替换 GPIOC->ODR=1<<5; //STB置高 PC5
GPIO_ResetBits(GPIOC,GPIO_Pin_5); 替换 GPIOC->ODR=0<<5;
 //STB置低 PC5
#include "tm1624.h"
const unsigned char  ledsw[11] = {0x00,0x01,0x02,0x06,0x0E,0x1E,0x03,0x07,0x0F,0x1F};				//亮灯个数ledsw[0/1/6/7/8/9]   亮5颗灯:ledsw[9]=0x1F=0001 1111 
const unsigned char  CODE[25]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0xBF,0X86,0XDB,0XCF,0XE6,0XED,0XFD,0X87,0XFF,0XEF,
0x71,   //20 -- 'F'    CODE[20]=0X71
0x77,   //21 -- 'A'
0x3E,   //22 -- 'U'   
0X40,   //23 -- ‘-’    CODE[23]=0X40=0100 0000 (dp-'G'-F-E-D-C-B-A)
0X00,   //无 24
};  //共阴数码管0~9 FHU字型码{0xBF,0X86,0XDB,0XCF,0XE6,0XED.0XFD,0X87,0XFF,0XEF}
/*
s[0] = 11   即CODE[11]  -> 0X86 -> 数字‘1’
s[1] = 12
s[2] = 13
s[3] = 14
CODE[s[0]]
CODE[s[1]]
CODE[s[2]]
CODE[s[3]]
*/
static void delay(unsigned int j)
{
  unsigned int i;
  for(i=0;i<j;i++)
  {
//				__NOP;
  }
}
//1624初始化函数
void TM1624_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB
	RCC_PCLKConfig(RCC_HCLK_Div1);   //APB
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);	//使能GPIOC时钟
//	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);	//使能GPIOD时钟
	//输出配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1;
	
	//PC3-4-5输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;  // (DIN PC3)  CLK PC4 STB PC5 
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
//	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;  // DIN PD3  
//	GPIO_Init(GPIOD, &GPIO_InitStructure);
}
//发送8bit数据,从低位开始
//参数 dat对应数据
static void send_8bit(unsigned char dat)	//发送8bit数据,从低位开始
{
  unsigned char i;
  
  for(i=0;i<8;i++)
  {	
//  	GPIOC->ODR=0<<4;         // PC4 CLK  低
		GPIO_ResetBits(GPIOC,GPIO_Pin_4);
		if(dat&0x01) 
//			GPIOC->ODR=1<<3;     // PC3 DIN  高
			GPIO_SetBits(GPIOC,GPIO_Pin_3);
		else     
//        GPIOC->ODR=0<<3;     // PC3 DIN  低
		GPIO_ResetBits(GPIOC,GPIO_Pin_3);
//	delay(1);
//	softWareDelay(10);
//	GPIOC->ODR=1<<4;					 // PC4 CLK  高 1bit数据在时钟的上升沿操作
		GPIO_SetBits(GPIOC,GPIO_Pin_4);
	  dat >>= 1;	 
  }
//  GPIOC->ODR=0<<4;           // PC4 CLK  低
//  GPIOC->ODR=0<<3;					 // PC3 DIN  低
	  GPIO_ResetBits(GPIOC,GPIO_Pin_4);
    GPIO_ResetBits(GPIOC,GPIO_Pin_3);
}
static void send_command(unsigned char cmd)  //发送命令字节
{ 
//   GPIOC->ODR=1<<5;					  //STB置高 PC5 
		GPIO_SetBits(GPIOC,GPIO_Pin_5);
//   delay(1);
//	 softWareDelay(10);
//   GPIOC->ODR=0<<5;					  //STB置低  
		GPIO_ResetBits(GPIOC,GPIO_Pin_5);
    send_8bit(cmd);			      //发送8bit数据
}
//1624刷新函数
//功能 设置数码管显示的数字和led显示个数
//参数 *s要显示的数字 *led要显示的led 
//返回 void
//调度周期 5ms
void digital_display_update(unsigned char *s,unsigned char *led)   //????,1~4??????0~9
{
    send_command(0x02); 	      //显示模式设置(00):6位12段模式(10)             (即:00 ---- 10)   
    send_command(0x40);	        //数据命令设置(01):测试模式设置为普通模式(0)--地址模式设置为地址自加(0)--读写模式(00)     (即:01 -- 0 0 00)
    send_command(0xC0);	        //地址设定(11):设置显示模式,从00H开始(0000)   (即:11 -- 0000)             
 
    send_8bit(CODE[s[0]]);     //第一个数码管grid1          digital_tmp[0] = 22 / 20 / 21 /24   即CODE[23]=0X40=0100 0000 (dp-'G'-F-E-D-C-B-A)
    send_8bit(0x00);           //grid1 高字节 seg9-seg14
    
    send_8bit(CODE[s[1]]);     //第二个数码管gid2
    send_8bit(0x00);           //grid2 高字节 seg9-seg14  
    send_8bit(CODE[s[2]]);     //第三个数码管
    send_8bit(0x00);           //grid3 高字节 seg9-seg14   
    
		send_8bit(CODE[s[3]]);     //第四个数码管
    send_8bit(0x00);           //grid3 高字节 seg9-seg14   
    
    send_8bit(ledsw[led[0]]);   //  YG1-YG5  左侧功率显示LED   led_tmp[0] = 0 / 1 / 6 / 7 / 8 / 9 例亮5颗灯:ledsw[9]=0x1F=0001 1111 
    send_8bit(0x00);            //  grid3 高字节 seg9-seg14
    
	  send_8bit(ledsw[led[1]]);   // YG6-YG10 右侧燃油显示LED
    send_8bit(0x00);            // grid3  seg9-seg14
																// 清空显示RAM(对所有RAM写0)
    send_command(0x8F);	        //显示控制指令设置(10),打开显示(1)并设置占空比14/16 (010) (即:10 -- 1 010)
//    GPIOC->ODR=1<<5;
}
参考资料
- [1] 国产航顺HK32F030M:TM1624四位数码管驱动显示
- [2] STM32入门笔记(02): GPIO工作原理、 GPIO通用和AFIO复用功能 I/O(SPL库函数版)



















