采用CSM32RV003开发板点亮6位数码管的段码屏的基本程序 - RISC-V MCU技术社区 - 电子技术william hill官网 - 广受欢迎的专业电子william hill官网 - 威廉希尔官方网站
分享 收藏 返回

[文章]

采用CSM32RV003开发板点亮6位数码管的段码屏的基本程序

CSM32RV003点亮6管段码屏

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脚驱动供电,一根连6LED背光,一条白色线接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;
}

*附件:MCS003_timer1.rar

更多回帖

×
发帖