1 、前言
今日翻开电子器件箱,偶然发现以前邮购的HT1621驱动的6位液晶显示的段码屏,该屏只有三个信号线,当时用51单片机驱动显示正常,决定用申请的南京中科微的CSM32RV003开发板试试能否成功。
2、HT1621 驱动程序文件: HT1621.h
段码屏正面右侧共****6 个引脚,自上而下依次是: 1/CS 、 2/WR 、 3/Data 、 4/GND 、 5/VCC(+5V) 、 6/LED+( 背光正极 ) 。
实验威廉希尔官方网站 :黑色的粗USB线引出****4 根线:绿线接 +5V ,白线接地。 6管数字段码屏用USB供电,一根绿线连5脚驱动供电,一根连6脚LED背光,一条白色线接4脚,另一条白色线接CSM32RV003 开发板的地,实现两块威廉希尔官方网站 板的共地。 CSM32RV003****开发板的 PA0 (黑线)、 PA2 (白线)、 PA3 (灰线)分别与段码屏的 1/CS 、 2/WR 、 3/Data****相连。
HT1621驱动程序根据适合51单片机的驱动程序修改,采用HT1621****驱动的其它段码屏可以参考此程序修改。
//采用CSM32RV003单片机的6位数码管段码液晶屏驱动程序 HT1621.h
//该段码液晶屏地址从最右边一位开始,共12个地址,每个数字占2个地址
#include "headfile.h"
// - - 定义接口
#define HT1621_CS_PIN0 PIN0 // - - HT1621使能,引脚1
#define HT1621_WR_PIN2 PIN2 // - - HT1621时钟,引脚2
#define HT1621_DAT_PIN3 PIN3 // - - HT1621数据,引脚3
#define BIAS 0x52 //0b1000 0101 0010 1/3偏压 4公共口
#define SYSDIS 0X00 //0b1000 0000 0000 关振系统荡器和LCD偏压发生器
#define SYSEN 0X02 //0b1000 0000 0010 打开系统振荡器
#define LCDOFF 0X04 //0b1000 0000 0100 关LCD偏压
#define LCDON 0X06 //0b1000 0000 0110 打开LCD偏压
#define XTAL 0x28 //0b1000 0010 1000 外部接时钟
#define RC256 0X30 //0b1000 0011 0000 内部时钟
#define TONEON 0X12 //0b1000 0001 0010 打开声音输出
#define TONEOFF 0X10 //0b1000 0001 0000 关闭声音输出
#define WDTDIS 0X0A //0b1000 0000 1010 禁止看门狗
// - - 定义子程序函数
void Ht1621_Init(void); // - - 初始化 HT1621
void Ht1621Wr_Data(uint8_t Data,uint8_t cnt); // - - HT1621 写入数据函数
void Ht1621WrCmd(uint8_t Cmd); // - - HT1621 写入命令函数
void Ht1621WrOneData(uint8_t Addr,uint8_t Data); // - - HT1621 在指定地址写入数据函数
void Ht1621WrAllData(uint8_t Addr,uint8_t *p,uint8_t cnt); // - - HT1621 连续写入数据函数
uint8_t dat_buf(uint8_t dat); //数字转段码子函数
/********************************************************
函数名称:void Ht1621_Init(void)
功能描述: HT1621初始化
全局变量:无
参数说明:无
返回说明:无
版 本:1.0
说 明:初始化后,液晶屏所有字段均显示
********************************************************/
void Ht1621_Init(void)
{
GPIO_MODE_Init(GPIOA,HT1621_CS_PIN0,GPIO_MODE_OUTPUT); //GPIO 模式
GPIO_MODE_Init(GPIOA,HT1621_WR_PIN2,GPIO_MODE_OUTPUT); //GPIO 模式
GPIO_MODE_Init(GPIOA,HT1621_DAT_PIN3,GPIO_MODE_OUTPUT); //GPIO 模式
GPIO_Write(GPIOA,HT1621_CS_PIN0,GPIO_SET); //GPIO 输出
GPIO_Write(GPIOA,HT1621_WR_PIN2,GPIO_SET); //GPIO 输出
GPIO_Write(GPIOA,HT1621_DAT_PIN3,GPIO_SET); //GPIO 输出
Delay32M_ms(2500); // - - 延时使LCD工作电压稳定
Ht1621WrCmd(BIAS); //-- 1/3偏压 4公共口
Ht1621WrCmd(RC256); // - - 使用内部振荡器
Ht1621WrCmd(SYSDIS); // - - 关振系统荡器和LCD偏压发生器
Ht1621WrCmd(WDTDIS); // - - 禁止看门狗
Ht1621WrCmd(SYSEN); // - - 打开系统振荡器
Ht1621WrCmd(LCDON); // - - 打开声音输出
}
/******************************************************
函数名称:void Ht1621Wr_Data(INT8UData,INT8Ucnt)
功能描述: HT1621数据写入函数
全局变量:无
参数说明:Data为数据,cnt为数据位数
返回说明:无
说 明:写数据函数,cnt为传送数据位数,数据传送为低位在前
*******************************************************/
void Ht1621Wr_Data(uint8_t Data,uint8_t cnt)
{
uint8_t i;
for (i = 0;i < cnt;i++)
{
GPIO_Write(GPIOA,HT1621_WR_PIN2,GPIO_RESET); //
Delay32M_us(10);
if(Data&0x80)
GPIO_Write(GPIOA,HT1621_DAT_PIN3,GPIO_SET); //
else
GPIO_Write(GPIOA,HT1621_DAT_PIN3,GPIO_RESET);
Delay32M_us(10);
GPIO_Write(GPIOA,HT1621_WR_PIN2,GPIO_SET); //
Delay32M_us(10);
Data <<= 1;
}
}
/********************************************************
函数名称:void Ht1621WrCmd(INT8UCmd)
功能描述: HT1621命令写入函数
全局变量:无
参数说明:Cmd为写入命令数据
返回说明:无
说 明:写入命令标识位100
********************************************************/
void Ht1621WrCmd(uint8_t Cmd)
{
GPIO_Write(GPIOA,HT1621_CS_PIN0,GPIO_RESET); //
Delay32M_us(10);
Ht1621Wr_Data(0x80,4); // - - 写入命令标志100
Ht1621Wr_Data(Cmd,8); // - - 写入命令数据
GPIO_Write(GPIOA,HT1621_CS_PIN0,GPIO_SET); //
Delay32M_us(10);
}
/********************************************************
函数名称:void Ht1621WrOneData(INT8UAddr,INT8UData)
功能描述: HT1621在指定地址写入数据函数
全局变量:无
参数说明:Addr为写入初始地址,Data为写入数据
返回说明:无
说 明:因为HT1621的数据位4位,所以实际写入数据为参数的后4位
********************************************************/
void Ht1621WrOneData(uint8_t Addr,uint8_t Data)
{
GPIO_Write(GPIOA,HT1621_CS_PIN0,GPIO_RESET); //
Ht1621Wr_Data(0xa0,3); // - - 写入数据标志101
Ht1621Wr_Data(Addr << 2,6); // - - 写入地址数据
Ht1621Wr_Data(Data << 4,4); // - - 写入数据
GPIO_Write(GPIOA,HT1621_CS_PIN0,GPIO_SET); //
Delay32M_us(10);
}
/********************************************************
函数名称:void Ht1621WrAllData(uint8_t Addr,uint8_t*p,uint8_t cnt)
功能描述: HT1621连续写入方式函数
全局变量:无
参数说明:Addr为写入初始地址,*p为连续写入数据指针,
cnt为写入数据总数
返回说明:无
说 明:HT1621的数据位4位,此处每次数据为8位,写入数据
总数按8位计算
********************************************************/
void Ht1621WrAllData(uint8_t Addr,uint8_t *p,uint8_t cnt)
{
uint8_t i;
GPIO_Write(GPIOA,HT1621_CS_PIN0,GPIO_RESET); //
Ht1621Wr_Data(0xa0,3); // - - 写入数据标志101
Ht1621Wr_Data(Addr << 2,6); // - - 写入地址数据
for (i = 0;i < cnt;i++)
{
Ht1621Wr_Data(*p,8); // - - 写入数据
p++;
}
GPIO_Write(GPIOA,HT1621_CS_PIN0,GPIO_SET); //
Delay32M_us(10);
}
/********************************************************
函数名称:uint8_t dat_buf(uint8_t dat)
功能描述: 把1位数码管的数字的各个段码和转为16进制数
参数说明:dat要显示的数字
返回说明: dpgfe为高4位的和,dcba为低4位的和,返回二者进行或运算的结果
********************************************************/
uint8_t dat_buf(uint8_t dat)
{ //邮购的6位数码管液晶屏,经测试低地址的8对应该位数码管左侧的小数点
//可以再编写一个类似的点亮点的函数
//a=1,b=2,c=4,d=8,e=4,f=1,g=2
uint8_t temp,dp, g,f,e,d,c,b,a; //数码管的段 dp gfedcba
switch(dat)
{ //显示数字0~9时各段的值,最高位dp=0
case 0 : dp=0;g=0;f=1;e=4;d=8;c=4;b=2;a=1;break;
case 1 : dp=0;g=0;f=0;e=0;d=0;c=4;b=2;a=0;break;
case 2 : dp=0;g=2;f=0;e=4;d=8;c=0;b=2;a=1;break;
case 3 : dp=0;g=2;f=0;e=0;d=8;c=4;b=2;a=1;break;
case 4 : dp=0;g=2;f=1;e=0;d=0;c=4;b=2;a=0;break;
case 5 : dp=0;g=2;f=1;e=0;d=8;c=4;b=0;a=1;break;
case 6 : dp=0;g=2;f=1;e=4;d=8;c=4;b=0;a=1;break;
case 7 : dp=0;g=0;f=0;e=0;d=0;c=4;b=2;a=1;break;
case 8 : dp=0;g=2;f=1;e=4;d=8;c=4;b=2;a=1;break;
case 9 : dp=0;g=2;f=1;e=0;d=8;c=2;b=2;a=1;break;
default :break;
} //分别取高4位的段码和、低4位的段码和并转为BCD码
temp = (( g + f + e + d) << 4) | (c + b + a);
return temp; //返回每个数码管显示数字对应的段码的BCD码
}
2、主程序文件:main.c
/*************************************************
\file main.c
\version V0.1, 2023-10-31, firmware for CSM32RV003
在原厂资料改003_reset_EN.zip的基础上改写 下载成功
使用原厂资料,要改动的地方在main.c中有说明
程序功能:
开机白色LED亮2s,然后熄灭,6位数字的段码屏逐段点亮,熄灭后显示:104556
红色指示灯500ms闪烁一次 下载成功 为何用自动生成的代码框架,中断函数不工作???
在原厂资料改003_reset_EN.zip的基础上改写则正常
********************************************************/
#include "headfile.h"
#include "HT1621.h" //段码屏HT1621头文件
uint8_t Ht1621Tab[12]; //定义长度为12的数组,默认初值全为0
uint8_t DateTime[ ]={56,45,10}; //10:45:56
//=======自定义内部函数声明区==============================
void display(void); //声明显示函数
//=============子程序区======================
void display(void) // 定义显示函数
{
uint8_t h1,h2,m1,m2,s1,s2; //定义存储变量
h1 = dat_buf(DateTime[2] / 10); //存储时的十位
h2 = dat_buf(DateTime[2] % 10); //存储时的个位
m1 = dat_buf(DateTime[1] / 10); //存储分的十位
m2 = dat_buf(DateTime[1] % 10); //存储分的个位
s1 = dat_buf(DateTime[0] / 10); //存储秒的十位
s2 = dat_buf(DateTime[0] % 10); //存储秒的个位
Ht1621WrOneData(0x0b,h1 >> 4 ); //写时的十位高位地址的4个段码
Ht1621WrOneData(0x0a,h1 & 0x0f ); //写时的十位低位地址的4个段码
Ht1621WrOneData(0x09,h2 >> 4 ); //写时的个位高位地址的4个段码
Ht1621WrOneData(0x08,h2 & 0x0f ); //写时的个位低位地址的4个段码
Ht1621WrOneData(0x07,m1 >> 4 ); //写分的十位高位地址的4个段码
Ht1621WrOneData(0x06,m1 & 0x0f ); //写分的十位低位地址的4个段码
Ht1621WrOneData(0x05,m2 >> 4 ); //写分的个位高位地址的4个段码
Ht1621WrOneData(0x04,m2 & 0x0f ); //写分的个位低位地址的4个段码
Ht1621WrOneData(0x03,s1 >> 4 ); //写秒的十位高位地址的4个段码
Ht1621WrOneData(0x02,s1 & 0x0f ); //写秒的十位低位地址的4个段码
Ht1621WrOneData(0x01,s2 >> 4 ); //写秒的个位高位地址的4个段码
Ht1621WrOneData(0x00,s2 & 0x0f ); //写秒的个位低位地址的4个段码
}
#define SFT ((SFT_TypeDef *)SFT_BASE)
#define SFT_BASE 0x30000360UL
volatile uint32_t NRST_EN;
#define LED_B_PA8 PIN8 //蓝B_LED 位置
#define LED_G_PA9 PIN9 //绿G_LED 位置
#define LED_R_PA12 PIN12 //红R_LED 位置
#define KEY_PA3 PIN3 //开关位置PA3
/********************************
//Timer1向上计数,根据原厂的timer.c修改
//修改要在timer.c中进行 !!!!!!!!!!!!!!!!!!!!!!!
//这里把该函数从timer.c中复制来
void Timer1_UpCounting_Mode_Init(void) //Timer1向上计数
{
TIMER1->CR1 = 0; //CR1[0]计数器开关:0-关闭,1-开启
TIMER_CLKEN->CLKEN |= 1; //CLKEN[8] Timer2时钟开关:1开启,0-关闭
//CLKEN[0] Timer1时钟开关:1开启,0-关闭
TIMER1->PSC = 32000-1; //预分频 32MHZ/1KHZ=32000,时钟1KHZ
TIMER1->ARR = 500-1; //自动重装寄存器 定时周期500ms
TIMER1->RCR = 0; //重复计数
TIMER1->IER = 1 << 0; //使能TIMER1中断:1-使能,0-关闭
}
*******************************************************************/
//有了如下的代码所以可以把中断函数的在此处修改
void Timer1_Update_IRQhandler(void) __attribute__((interrupt("SiFive-CLIC-preemptible"))); //该函数在原厂的it.h中
void Timer1_Update_IRQhandler(void) //原函数在原厂的it.c中,要把it.c中的该函数注释掉
{
Timer1_Update_Isr();
}
void Timer1_Update_Isr(void) //更新 //该函数在原厂的timer.c中,要把它注释掉
{
if(TIMER1->SR&0x1)
{
TIMER1->SR &= ~0x1; //原厂的
//TIMER1->SR &= ~(0x1 << 0); //一样的
GPIO_Toggle(GPIOA,LED_R_PA12 ); //红灯闪烁,间隔500ms
display( ) ; //HT1621段码屏显示,500ms刷新一次
}
}
int main(void)
{
typedef struct
{
volatile uint32_t EN;
volatile uint32_t NRST_EN;
}SFT_TypeDef;
SFT->NRST_EN=0; //使能MCU003PA15硬件复位@
///----Chapter 5 GPIO Test Init ---------------------------------------------------------------------------------
//输出端口的设置
GPIO_MODE_Init(GPIOA,LED_B_PA8,GPIO_MODE_OUTPUT); //GPIO的PA8输出模式
GPIO_MODE_Init(GPIOA,LED_G_PA9 ,GPIO_MODE_OUTPUT); //端口初始化,PA9输出模式
GPIO_MODE_Init(GPIOA,LED_R_PA12,GPIO_MODE_OUTPUT); //GPIO的PA12输出模式
//为了驱动不同的负载,可以设置不同的输出方式
//GPIO_OutType_Init(GPIOA,PIN12,GPIO_OTYPE_ODOS_ON ); //PA12推免输出
//GPIO_OutType_Init(GPIOA,PIN12,GPIO_OTYPE_ODOS_OFF ); //PA12 关闭开漏、开源功能
//GPIO_OutType_Init(GPIOA,PIN12,GPIO_OTYPE_OS_ON ); //PA12开源输出
//GPIO_OutType_Init(GPIOA,PIN12, GPIO_OTYPE_ODOS_OFF); //PA12关闭开漏、开源功能
//GPIO_OutType_Init(GPIOB,PIN10, GPIO_OTYPE_ODOS_OFF); //PB10关闭开漏、开源功能
/***************************************************************/
//点亮开发板上的三基色LED灯2s
GPIO_Write(GPIOA, LED_G_PA9,GPIO_RESET); //GPIO的PA9输出0
//GPIO_Write(GPIOA,PIN9, SET); //GPIO的PA9输出1
GPIO_Write(GPIOA, LED_B_PA8 ,GPIO_RESET); //GPIO的PA8 输出0
GPIO_Write(GPIOA, LED_R_PA12,GPIO_RESET); //GPIO的PA12 输出0
Delay32M_ms(2000); //调用32MHZ系统的延时函数 延时2s
//熄灭开发板上的三基色LED
GPIO_Write(GPIOA, LED_B_PA8 ,GPIO_SET); //PA8输出1 PA8接Blue LED 低电平LED亮 关闭
GPIO_Write(GPIOA,LED_G_PA9,1); //PA9输出1 PA9接Green LED 低电平LED亮 关闭
GPIO_Write(GPIOA,LED_R_PA12,1); //PA12输出 PA9接RED LED 低电平LED亮 关闭
//输入口的设置
GPIO_InType_Init( GPIOA, KEY_PA3,GPIO_MODE_INPUT); //GPIO的PA3输入模式,外接按键
//GPIO_PULL_Init(GPIOA, KEY_PA3, GPIO_PULLUP); //PA3 上拉 未按下时是1
GPIO_PULL_Init(GPIOA, KEY_PA3, GPIO_PULLDOWN); // PA3下拉 未按下时是0
//GPIO_PULL_Init(GPIOA, KEY_PA3, 0GPIO_NOPULL ); // PA3浮空
GPIO_MODE_Init(GPIOA, PIN12,GPIO_MODE_OUTPUT); //GPIO 模式
GPIO_Write(GPIOA, PIN12,GPIO_SET); //GPIO 输出
/***********Ht1621驱动的段码屏部分*************************************/
Ht1621_Init( ); // - - 初始化 HT1621
Ht1621WrAllData(0,Ht1621Tab ,12); //连续写入数据0,清除1621寄存器数据,即清屏
//逐个点亮各段,1个“8.”共2个地址,每个地址写1/2/4/8点亮,地址从0开始,顺序加1
//也可以一次点亮1个段
for (uint8_t i = 0;i < 12;i+=2) //共12个地址
{
Ht1621WrOneData(0x0+i,1 ); //点亮1个段
Delay32M_ms(500); //延时便于观察
Ht1621WrOneData(0x0+i,3 ); //点亮2个段
Delay32M_ms(500);
Ht1621WrOneData(0x0+i,7 ); //点亮3个段
Delay32M_ms(500);
Ht1621WrOneData(0x0+i,15 ); //点亮4个段
Delay32M_ms(500);
Ht1621WrOneData(0x01+i,1 ); //点亮5个段
Delay32M_ms(500);
Ht1621WrOneData(0x01+i,3 ); //点亮6个段
Delay32M_ms(500);
Ht1621WrOneData(0x01+i,7 ); //点亮7个段
Delay32M_ms(500);
Ht1621WrOneData(0x01+i,15 ); //点亮8个段
Delay32M_ms(500);
}
Ht1621WrAllData(0,Ht1621Tab ,12); //连续写入数据0,清除1621寄存器数据,即清屏
//这里中断设置放LED及按键等的后边,开机三个LED同时发光2s,然后中断动作
///---------- System Init ----------///
CLIC_Init();//系统中断配置
//SysClock_RC_Mode_Init(); //系统时钟初始化:RC模式
//SysClock_Crystal_Mode_Init(); //系统时钟初始化:晶振模式
//SysClock_PLL_Mode_Init(); //系统时钟初始化:PLL模式
SysClock_Test_Init(); //系统时钟初始化
Timer1_UpCounting_Mode_Init( ); //Timer1向上计数,有修改
Interrupt_Level(TIMER1_updata_int_ID,INT_LEVEL0); //CLIC设置中断抢占级别 优先级 lic.h中
Interrupt_Enable(TIMER1_updata_int_ID); //CLIC使能中断 允许Timer1溢出中断
//使能系统总中断
SYS_Interrupt_Enable( ); //CLIC开总中断
while(1);
return 0;
}
更多回帖