STM32L476VET6 RTC时钟日历(HAL库+CubeMX开发)(三)ST7920LCD液晶屏幕驱动和延时函数

LCD液晶屏驱动

#ifndef __LCD_st7920__
#define __LCD_st7920__

#include "sys.h"

#define LCD_35V_CTL_H				HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET)
#define LCD_35V_CTL_L  				HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET)

#define  LCD_ST7920_DATAIO   GPIO_PIN_8 |  GPIO_PIN_9 |  GPIO_PIN_10 |  GPIO_PIN_11 |  GPIO_PIN_12 |  GPIO_PIN_13 |  GPIO_PIN_14 |  GPIO_PIN_15

#define  LCD_ST7920_RS_ON   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);
#define  LCD_ST7920_RW_ON   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
#define  LCD_ST7920_E_ON    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
#define  LCD_ST7920_PSB_ON   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_SET);
#define  LCD_ST7920_RST_ON   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET);

#define  LCD_ST7920_RS_OFF   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
#define  LCD_ST7920_RW_OFF   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
#define  LCD_ST7920_E_OFF    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
#define  LCD_ST7920_PSB_OFF   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_0, GPIO_PIN_RESET);
#define  LCD_ST7920_RST_OFF   HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);

//液晶电源MOS控制:
#define LCD_35V_CTL_H				HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET)
#define LCD_35V_CTL_L  			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET)
#define LED_35V_CTL_H				HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET)
#define LED_35V_CTL_L  			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET)

#define LCD_FRAME_SIZE			50


typedef  struct            
{  
	u8 lcd_busy_overtime;
}DISP_DEAL_T;

extern u8 LCD_FRAME_STR[LCD_FRAME_SIZE];
extern DISP_DEAL_T  lcd;


void LCD_ST7920_DataIO_Set_In(void);//LCDst7920端口初始化,配置为输入
void LCD_ST7920_DataIO_Set_Out(void);//LCDst7920端口初始化,配置为输出
void Chk_Busy(void);//..........测忙..........
void LCD_ST7920_WriteCmd(u16 cmd);//用于写指令
void LCD_ST7920_WriteData(u16 data);//用于写数据
u8 LCD_ST7920_SetAddress(u8 x,u8 y);//显示坐标写入函数
int LCD_ST7920_ShowStr(unsigned char x,unsigned char y,unsigned char *str);//LCDst7920显示字符串
int LCD_ST7920_ShowSetChar(u8 x,u8 y,u8 *str,u8 num);//显示设定数量的字符
void LCDClrDisplay(void);//清屏
void LCD_ST7920_Init(void);//液晶初始化函数
void LCD_ST7920_DeInit(void);//液晶关闭函数
void LCD_Display(void);

#endif
#include "lcd_st7920.h"
#include "delay.h"
#include "rtc.h"
#include "stdio.h"

DISP_DEAL_T  lcd={0};
u8 LCD_FRAME_STR[LCD_FRAME_SIZE];

void LCD_ST7920_DataIO_Set_In(void)//LCDst7920端口初始化,配置为输入
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = LCD_ST7920_DATAIO;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;//输入浮空
	GPIO_InitStruct.Pull = GPIO_NOPULL;//GPIO_PULLUP;
	HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}

void LCD_ST7920_DataIO_Set_Out(void)//LCDst7920端口初始化,配置为输出
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = LCD_ST7920_DATAIO;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;	
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}

//..........测忙..........
void Chk_Busy(void)
{
	LCD_ST7920_DataIO_Set_In();
	LCD_ST7920_RS_OFF;
	LCD_ST7920_RW_ON;
	LCD_ST7920_E_ON;
	DelayUs(2);
	lcd.lcd_busy_overtime=20;//100ms
	while(((GPIOD->IDR)&0x8000)!=0&&lcd.lcd_busy_overtime!=0);
	LCD_ST7920_E_OFF;
}

/**
 * @brief	  LCDst7920 命令写入函数
 * @param   cmd 写入命令值			
 */
void LCD_ST7920_WriteCmd(u16 cmd)//用于写指令     //修改ODR值的赋值方式,避免PD8-16端口操作影响PD0-7端口的正常使用  DMS-20220528
{
  	u16 cmd_tmp;
	Chk_Busy();//等待液晶准备好
	LCD_ST7920_DataIO_Set_Out();
  	LCD_ST7920_RS_OFF;//写指令
  	LCD_ST7920_RW_OFF;

	cmd_tmp =cmd<< 8;//((((cmd&0x0080) << 1))+(((cmd&0x0040) << 3))+(((cmd&0x0020) << 5))+(((cmd&0x0010) << 7))
							//+(((cmd&0x0008) << 9))+(((cmd&0x0004) << 11))+(((cmd&0x0002) << 13))+(((cmd&0x0001) << 15)));    
		//DelayUs(50);
	GPIOD->ODR= (GPIOD->ODR & 0x00FF)|cmd_tmp;
	
	DelayUs(100);
	LCD_ST7920_E_ON;
	DelayUs(250);
	LCD_ST7920_E_OFF;
}

/**
 * @brief	  LCDst7920 数据写入函数
 * @param   data写入数据值	
 */
void LCD_ST7920_WriteData(u16 data)//用于写数据    //修改ODR值的赋值方式,避免PD8-16端口操作影响PD0-7端口的正常使用  DMS-20220528
{
	u16 data_tmp;
	Chk_Busy();//等待液晶准备好
	LCD_ST7920_DataIO_Set_Out();
  	LCD_ST7920_RS_ON;	//写数据
  	LCD_ST7920_RW_OFF;

	data_tmp =data<< 8;//((((data&0x0080) << 1))+(((data&0x0040) << 3))+(((data&0x0020) << 5))+(((data&0x0010) << 7))
							//+(((data&0x0008) << 9))+(((data&0x0004) << 11))+(((data&0x0002) << 13))+(((data&0x0001) << 15)));
		//DelayUs(50);
	GPIOD->ODR= (GPIOD->ODR & 0x00FF)|data_tmp;
	
	DelayUs(100);
	LCD_ST7920_E_ON;
	DelayUs(250);//
	LCD_ST7920_E_OFF;
}

/**
 * @brief	  LCDst7920 显示坐标写入函数
 * @param  输入参数 x:0~7 0~15  y:0~3  vvvvvvvvvvvvvvvvvv输出参数 1:参数错误  0:执行成功	
 */
u8 LCD_ST7920_SetAddress(u8 x,u8 y)
{
	if((x>7)||(y>3))
	return 1;
	LCD_ST7920_WriteCmd(0x30);	/*30H--基本指令动作*/
	if(y == 0)
	{LCD_ST7920_WriteCmd(0x80|x);}//从第 1 行开始显示}
	else if ( y == 1 )
	{LCD_ST7920_WriteCmd(0x90|x);}//从第 2 行开始显示}
	else if( y == 2 )
	{LCD_ST7920_WriteCmd(0x88|x);}//从第 3 行开始显示
	else
	{LCD_ST7920_WriteCmd(0x98|x);}//从第 4 行开始显示
	return 0; 
}

/**
 * @brief	  LCDst7920 显示字符串函数
 *
 * @remark	
* @param  输入参数 x:0~15  y:0~1  *str:字符串首地址  输出参数 1:参数错误  0:执行成功
* @return  				
*/
int LCD_ST7920_ShowStr(unsigned char x,unsigned char y,unsigned char *str)//LCDst7920显示字符串
{
//	if(key_set.wakeup_flg!=1)
//		return 0;
	
	if(LCD_ST7920_SetAddress(x,y))    //设置数据地址指针
	return 1;	
	while(*str !='\0')
	LCD_ST7920_WriteData(*str++);//写数据
	return 0;  
}

//显示设定数量的字符
int LCD_ST7920_ShowSetChar(u8 x,u8 y,u8 *str,u8 num)//显示设定数量的字符
{
	u8 i;
//	if(key_set.wakeup_flg!=1)
//		return 0;
	
	if(LCD_ST7920_SetAddress(x,y))    //设置数据地址指针
	return 1;	
	for(i=0; i<num; i++)
		LCD_ST7920_WriteData(*str++);//写数据
	return 0;  
}

//..........清屏DDRAM..........
void LCDClrDisplay(void)
{
	LCD_ST7920_WriteCmd(0x30);	/*30H--基本指令动作*/
	LCD_ST7920_WriteCmd(0x01);	/*清屏,地址指针指向00H*/
}

/**
 * @brief	  LCDst7920 液晶初始化函数	
 */          
void LCD_ST7920_Init(void)//液晶初始化函数
{
	
	LCD_35V_CTL_L;//供电
	LCD_ST7920_RST_ON;
	LCD_ST7920_PSB_ON;
	LED_35V_CTL_L;//3.5v电源芯片使能
	DelayMs(50);
	LCDClrDisplay();//清屏
	//DelayMs(150);
	LCD_ST7920_WriteCmd(0x06);	/*光标的移动方向*/
	LCD_ST7920_WriteCmd(0x0c);	/*开显示,关光标*/
}


void LCD_ST7920_DeInit(void)//液晶关闭函数
{
	
	LCD_35V_CTL_H;//LCD关闭供电
	LED_35V_CTL_H;//3.5v电源芯片失能
	LCD_ST7920_RST_OFF;
	LCD_ST7920_PSB_OFF;
}


void LCD_Display(void)
{
	sprintf((char*)LCD_FRAME_STR, "%04d/%02d/%02d", 2000+Date.Year,Date.Month,Date.Date);
	LCD_ST7920_ShowStr(0,0,(unsigned char *)LCD_FRAME_STR);
	
	switch(Date.WeekDay)
	{
		case 0x01:
			LCD_ST7920_ShowStr(0,1,(unsigned char *)"MONDAY");
			break;
		case 0x02:
			LCD_ST7920_ShowStr(0,1,(unsigned char *)"TUESDAY");
			break;
		case 0x03:
			LCD_ST7920_ShowStr(0,1,(unsigned char *)"WEDNESDAY");
			break;
		case 0x04:
			LCD_ST7920_ShowStr(0,1,(unsigned char *)"THURSDAY");
			break;
		case 0x05:
			LCD_ST7920_ShowStr(0,1,(unsigned char *)"FRIDAY");
			break;
		case 0x06:
			LCD_ST7920_ShowStr(0,1,(unsigned char *)"SATURDAY");
			break;
		case 0x07:
			LCD_ST7920_ShowStr(0,1,(unsigned char *)"SUNDAY");
			break;
	}

	
	sprintf((char*)LCD_FRAME_STR, "%02d:%02d:%02d", Time.Hours,Time.Minutes,Time.Seconds);
	LCD_ST7920_ShowStr(0,2,(unsigned char *)LCD_FRAME_STR);
}

Chk_Busy函数里lcd.lcd_busy_overtime=20在tim2里每5ms进一次定时器中断,20*5=100ms

//tim.c

/* USER CODE BEGIN 1 */
/**********************************************
功能说明: 定时器中断回调函数
入口参数: 
返回参数: 
***********************************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	//5ms
	if(htim == (&htim2))
	{	
		//消抖+长短按检测
		if(!ks.key_dpress_flag)
		{
			ks.key_dpress_count++;
			if(ks.key_dpress_count>=6)//消抖6*5ms=30ms
			{
				if((HAL_GPIO_ReadPin(GPIOE,KEY_1_EXTI7_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_2_EXTI6_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_3_EXTI5_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_4_EXTI4_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_5_EXTI3_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_6_EXTI2_Pin))==GPIO_PIN_RESET)//按键按下消抖
				{
					ks.key_dpress_flag=1;//按键按下标志位置1直到上升沿再次触发
					ks.key_dpress_count=0;
					ks.key_duration_flag=0;
					GetKeyValue();
					KeyDeal();
				}
				if((HAL_GPIO_ReadPin(GPIOE,KEY_1_EXTI7_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_2_EXTI6_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_3_EXTI5_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_4_EXTI4_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_5_EXTI3_Pin)&\
					HAL_GPIO_ReadPin(GPIOE,KEY_6_EXTI2_Pin))==GPIO_PIN_SET)//按键抬起消抖
				{
					ks.key_dpress_flag=1;//按键按下标志位置1直到下降沿再次触发
					ks.key_dpress_count=0;
					ks.key_duration_flag=1;
					ks.key_duration*=0.005;
					printf("key_duration:%05.2fs\r\n",ks.key_duration);
					printf("\r\n");
				}
			}
		}
		//按键按下计时
		if(!ks.key_duration_flag)
		{
			ks.key_duration++;
		}
		
		//低功耗计时
		if(!low_pwr_struct.low_pwr_flag)
		{
			low_pwr_struct.low_pwr_count--;
			if(low_pwr_struct.low_pwr_count<0)//1min
			{
				low_pwr_struct.low_pwr_flag=1;
				low_pwr_struct.low_pwr_count=0;
				LOW_PWR_Enter();
			}
		}


		//LCD忙检测超时
		if(lcd.lcd_busy_overtime>0)
		{
			lcd.lcd_busy_overtime--;
		}
		
	}
	
	//100us	
	if(htim == (&htim3))
	{
  
	}
}

延时函数

#ifndef __DELAY_H
#define __DELAY_H 			   
#include "sys.h" 
 
	 
void DelayInit(void);
void DelayMs(unsigned int nms);
void DelayUs(unsigned int nus);

#endif


#include "delay.h"

static unsigned int  fac_us=0;							//us延时倍乘数			   
static unsigned int  fac_ms=0;							//ms延时倍乘数

			   
/**********************************************
功能说明: 延时功能初始化
入口参数:  
返回参数: 
***********************************************/
void DelayInit(void)
{
	HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);
  fac_us = 10;	
	fac_ms=(unsigned int)fac_us*1000;					    				//每个ms需要的systick时钟数	
}								    


/**********************************************
功能说明: 微秒延时函数
入口参数: 
返回参数: 
***********************************************/		    								   
void DelayUs(unsigned int nus)
{		
	unsigned int temp;	    	 
	SysTick->LOAD=nus*fac_us; 					      		//时间加载	  		 
	SysTick->VAL=0x00;        					      		//清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;			//开始倒数	  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		 			//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; 			//关闭计数器
	SysTick->VAL =0X00;      					       			//清空计数器	 
}

/**********************************************
功能说明:毫秒延时函数
入口参数: 
返回参数: 
***********************************************/
void DelayMs(unsigned int nms)
{	 		  	  
	unsigned int temp;		   
	SysTick->LOAD=(unsigned int)nms*fac_ms;				//时间加载(SysTick->LOAD为24bit)
	SysTick->VAL =0x00;							      				//清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;			//开始倒数  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));					//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;			//关闭计数器
	SysTick->VAL =0X00;       										//清空计数器	  	    
} 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值