问题描述:
航顺单片机 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库函数版)