【国产中颖】SH79F9202U单片机驱动LCD段码液晶学习笔记

news2024/9/20 8:08:19

在这里插入图片描述

1. 引言

因新公司之前液晶数显表产品单片机一直用的是 C51单片机(SH79F9202U9),本人之前没有接触过这款单片机,为了维护老产品不得不重新研究研究这款单片机。

10位ADC + LCD的增强型8051微控制器

SH79F9202是一种高速高效率8051可兼容单片机。在同样振荡频率下,较之传统的8051芯片它有着运行更快速的优越特性。

SH79F9202保留了标准8051芯片的大部分特性。这些特性包括内置256字节RAM,2个UART,外部中断0/2/3和外部中断4(8路输入)。此外,SH79F9202还集成了外部1280字节RAM,以及程序存储的最大32K字节Flash,此外还集成了最大4K类EEPROM,用于在系统掉电后保存数据。

SH79F9202不仅集成了如UART等标准通讯模块,此外还集成了LCD驱动器(内建LCD电压稳定电路、电容型偏压电路和电阻型偏压电路),PCA,PWM,10Bit ADC等模块。

为了达到高可靠性和低功耗,SH79F9202内建看门狗定时器,低电压复位功能及系统时钟监控功能。此外SH79F9202还提供了2种低功耗省电模式。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 开发环境搭建

  • 所需硬件
    • SH79F9202U 电路板
    • LCD段码液晶屏
    • SinoLink Plus 仿真器(见1.文档中的《中颖仿真器使用手册》)
  • 所需软件
    • Keil C51编译器 C51V961(见2.中颖开发工具包)
    • keil插件集成包】Sinowealth_KEIL_Setup_V3.8.13.9.1.7(见2.中颖开发工具包)
  • 开发环境安装与配置
    • Keil μVision 安装好后要根据需要,代码里面的寄存器初始化和keil里面的代码选项配置保持一致。
      在这里插入图片描述

在这里插入图片描述

3. SH79F9202U单片机资源介绍

基本IO介绍

在这里插入图片描述

// Note:配置为输出时,对应的IO上拉需关闭以降低功耗
void IO_Init()
{
	P0PCR = 0x00; //端口上拉电阻控制寄存器
	P0CR = 0XFF; // 端口控制寄存器  0:输入模式1:输出模式
	P0 = 0X00;  //端口数据寄存器
    P0_4 = 1; // P0.4端口输出高电平
    
	P1PCR = 0X00;
	P1CR = 0XFF;
	P1 = 0X00;

	P2PCR = 0X00;
	P2CR = 0XFF;
	P2 = 0X00;

	P3PCR = 0X00;
	P3CR = 0XFE;
	P3 = 0X00;

	P4PCR = 0X00;
	P4CR = 0XFF;
	P4 = 0X00;

	P5PCR = 0X04;  // 开启上拉
	P5CR = 0XFB;  // P5_2 输入模式
	P5 = 0X00;	 //P5_2 input
}
中断

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

更加详细的中断介绍还是要仔细看芯片手册,这里为了方便查阅放几张截图。

在这里插入图片描述

定时器外设
  • 注意:定时器的相关寄存器配置和Keil软件上的程序选项配置保持一致
#include "timer2.h"

// 20ms 
void INT_TIMER2(void) interrupt 5  
{ 
  static unsigned char counter = 0;
	
	TF2 = 0; // 清除中断标志
	++counter;
	if(counter >= 25) // 500ms
	{
		Test_Num++;
//		 P0_4 = !P0_4; // 翻转输出
		 counter = 0;
	}
		LCD_Data_OK(Test_Num);
		// LCD显示内容
		LCD_Data_Show();
}

void Delays(int del)
{
 	while(del--);
}


//OSC = 24M
//sysclk OSC / 2 = 12M
void Timer2_Init(void)
{
 	CLKCON = 0x08;        //【打开HFON】内部24MHz RC振荡器
 	Delays(2000);         //至少等待振荡器预热时间       
 	CLKCON |= 0x04;       //【选择FS】24M/8M Hz为OSCSCLK
 	CLKCON |= 0x20;       //【分频器CLKS[0:1]】fSYS = fOSCS/2
 
 	//12M/12 = 1M = 1us(T=1/f)  定时20ms 
	P0PCR = 0x00; // 输出模式 关闭上拉电阻
 	P0CR |= 0X10; // P0_4 GPIO设置为输出模式 
 
 	T2CON = 0;							// 停止定时器2
 	T2MOD = 0x00;           //  TCK = 12/12 = 1M    系统时钟的1/12|P1.0时钟输入或IO端口|递增计数
 	
/*如果EXEN2 = 0,定时器2递增到0FFFFH,在溢出后置起TF2位,同时定时器自动将用户软件写好的寄存器RCAP2H和RCAP2L的16位值装入TH2和TL2寄存器。
*/
	//初始值 45535   2^16=65536 
 	TH2 = 45535 >> 8;        // 取高位(177=1011 0001) = 1011 0001 1101 1111 >> 8 
	TL2 = 45535 & 0x00FF;    // 取低位 (223=1101 1111)  = 1011 0001 1101 1111 & 0000 0000 1111 1111    
		                     // TH2+TL2 = 1011 0001 1101 1111 =45535
	
	//重载值 45535
 	RCAP2H = 45535 >> 8;
 	RCAP2L = 45535 & 0x00FF;    //重载值

	// 自动重载值=65536-45535=20001
	
 	IEN0 |= 0x20;          //开中断  定时器2溢出中断
 	T2CON |= 0x04;         //开始定时器2 即寄存器0000 0100
 	EA = 1;							 	 // 开启总中断
// 	while(1);
}



//IPL1 = 0X01;
//IPH1 = OX01;

4. LCD段码液晶屏参数介绍

  • LCD段码液晶屏技术参数
    在这里插入图片描述

5. 根据LCD液晶屏的真值表写数字译码和驱动程序

根据液晶屏的工作原理和真值表的结构,设计一个数字译码算法,将数字或字符转换为对应的 SEG 和 COM 值。

LCD 真值表

在这里插入图片描述

数字译码

在这里插入图片描述

在这里插入图片描述

基于真值表,编写数字译码表和相应的驱动程序。

源文件 LCD.c

#include "LCD.h"

xdata unsigned char  LCD_SEG[SEGSIZE] _at_ 0x500; // LCD显示地址 指定位置为0x500

//时间/频率/电压显示				     // 0     1    2    3    4    5    6    7    8    9
const unsigned char Disp_Code[]={0xf5,0x05,0xd3,0x97,0x27,0xb6,0xf6,0x15,0xf7,0xb7,// 不带小数点显示
0xfd,0x0d,0xdb,0x9f,0x2f,0xbe,0xfe,0x1d,0xff,0xbf // 带小数点显示
};//显示数字译码

//功率显示                          // 0    1    2    3    4    5    6    7    8    9
const unsigned char DispPower_Code[]={0xfd,0x85,0xdb,0x9f,0xa7,0xbe,0xfe,0x95,0xff,0xbf};// 数字译码  "POWER" ":" "."这几个符号常亮



//Note:需在(Keil C51)Option中进行选择LCD为电容型
//为更有效的使用电容型LCD驱动器,用户必须先设置PUMPON,LCDON位之外的所有控制位,然后设置PUMPON位,
//在延迟之后(至少50ms)打开LCD,即LCDON位置1,点亮LCD面板;
void LCD_Init(void)
{
	unsigned char i,j;
 	LCDCON = 0x4F;   //0100 1111      LCDON|PUMPON|DUTY(1/4占空比,1/3偏置)|TYPESEL|   1111:VLCD = 1.000VDD 注意:当选择电容型LCD驱动时,此4位无效
	
	LCDCON1 = 0x00;  // 电阻型LCD驱动控制器寄存器
	
	DISPCLK0 = 0x00; // LCD驱动时钟分频寄存器 1/4   128K RC 对应的LCD帧频为256/4=64Hz
  DISPCLK1 = 0x03; // LCD驱动Pump寄存器 4K
	
	LCDSEL = 0x00;   // 闪烁模式控制寄存器  00 无闪烁功能
	
	// 模式选择寄存器
	P0SS = 0x83 ;     // P0_7/1/0 作为SEG13~15
	P1SS = 0xFF ;     // P1_7-P1.0作为SEG5~12
	P2SS = 0xFF ;			// P2_7-P2_4作为COM1~COM4 , P2_3-P2_0 即SEG1~4 
	P3SS = 0x00 ;     // P3_7-P3_0作为I/O,SEG25~32
	P4SS = 0x00 ;     // P4_6-P4_0作为I/0,SEG18~24
	P5SS = 0x0C ;     // P5_3/2   作为SEG16/17
	
	for(i=0;i<250;i++)	   	// Delay  50ms 以上再打开LCD 模块
	{
		for(j=0;j<250;j++);
	}
	LCDCON |= 0X80;			// 打开 LCD 模块
}

void LCD_Show(unsigned char udata)
{
	unsigned char i;
	for(i=0;i<SEGSIZE;i++)
  {
		LCD_SEG[i] = udata;
	}
	
}

// 数据处理
void LCD_Data_Show(void){
	
    // 电压 /频率/时间显示
		LCD_SEG[0] = Disp_4H;  // 千位
		LCD_SEG[1] = Disp_4L;
	
		LCD_SEG[2] = Disp_3H;  // 百位
		LCD_SEG[3] = Disp_3L;
	
		LCD_SEG[4] = Disp_2H;  // 十位
		LCD_SEG[5] = Disp_2L;
	
		LCD_SEG[6] = Disp_1H;  // 个位
		LCD_SEG[7] = Disp_1L;
    // V H z 时钟符号显示 
		LCD_SEG[8] = 0x03;
	
	  // 功率显示
		LCD_SEG[14] = DispPower_3H;   
		LCD_SEG[13] = DispPower_3L;  // 百位
		
		LCD_SEG[12] = DispPower_2H;   
		LCD_SEG[11] = DispPower_2L;  // 十位
		
		LCD_SEG[10] = DispPower_1H;  
		LCD_SEG[9] =  DispPower_1L;  // 个位

		// 油位显示
		LCD_SEG[15] = 0x0f;
		LCD_SEG[16] = 0x0f;
//	
}

void LCD_Data_OK(unsigned long disp_data){
	
	//
	Disp_Data = disp_data;
	
	b4 = Disp_Data /1000%10; // 千位
	b3 = Disp_Data /100%10;  // 百位
	b2 = Disp_Data /10%10;   // 十位
	b1 = Disp_Data %10;      // 个位 
	
// 带小数点显示
//	b4 = Disp_Data /1000%10 + 10; // 千位
//	b3 = Disp_Data /100%10 + 10;  // 百位
//	b2 = Disp_Data /10%10 + 10;   // 十位
//	b1 = Disp_Data %10;      // 个位 
	
//------------------------------------------------------------------

	Disp_4H = (Disp_Code[b4])>>4;
	Disp_4L = (Disp_Code[b4])&0x0F;
	
	Disp_3H = (Disp_Code[b3])>>4;
	Disp_3L = (Disp_Code[b3])&0x0F;
	
	Disp_2H = (Disp_Code[b2])>>4;
	Disp_2L = (Disp_Code[b2])&0x0F;
	
	Disp_1H = (Disp_Code[b1])>>4; // 个位
	Disp_1L = (Disp_Code[b1])&0x0F;
	
//------------------------------------------------------------------	
	DispPower_3H = (DispPower_Code[b3])>>4;
	DispPower_3L = (DispPower_Code[b3])&0x0F;
	
	DispPower_2H = (DispPower_Code[b2])>>4;
	DispPower_2L = (DispPower_Code[b2])&0x0F;
	
	DispPower_1H = (DispPower_Code[b1])>>4;// 个位
	DispPower_1L = (DispPower_Code[b1])&0x0F;
	

	if(Disp_Data < 1000) // 当显示数值是"0321"时,不显示前面的"0"   
	{
		Disp_4H = 0;
		Disp_4L = 0;
		if(Disp_Data < 100)
		{
			Disp_3H = 0;
			Disp_3L = 0;
			if(Disp_Data < 10)
			{
				Disp_2H = 0;
				Disp_2L = 0;
			}
		}
	}
}


头文件LCD.h

#ifndef   __LCD_H
#define   __LCD_H

#include "SH79F9202.h"
#include "cpu.h"


#define SEGSIZE   17

extern xdata unsigned char  LCD_SEG[SEGSIZE]; // LCD显示地址 指定位置为0x500

//时间/频率/电压显示	
extern const unsigned char Disp_Code[];
//功率显示 
extern const unsigned char DispPower_Code[];

static volatile unsigned long	Disp_Data=0; // 显示数据

static volatile unsigned char b1,b2,b3,b4; // 存放 个/十/百/千/万位的数值
static volatile unsigned char Disp_1H,Disp_1L,Disp_2H,Disp_2L,Disp_3H,Disp_3L,Disp_4H,Disp_4L;		//显示数据预处理值
static volatile unsigned char DispPower_1H,DispPower_1L,DispPower_2H,DispPower_2L,DispPower_3H,DispPower_3L;//显示数据预处理值(功率)

void LCD_Init(void);
void LCD_Show(unsigned char udata);		
void LCD_Data_Show(void);                   // LCD显示内容
void LCD_Data_OK(unsigned long disp_data);

#endif


资料下载

  • 参考资料和文献
  • 示例代码下载链接

参考资料

  • 【CSDN】编程圈子-谢厂节的博客
    这个大纲提供了从基础到实际应用的全面指导,可以帮助你系统地学习和掌握使用SH79F9202U单片机驱动LCD段码液晶屏的技能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1715535.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5G工厂长啥样

5G工厂是一种新型的工业互联网基础设施&#xff0c;利用5G为代表的新一代信息通信技术集成&#xff0c;打造新型工业互联网基础设施。在5G工厂中&#xff0c;自动化和智能化设备广泛使用&#xff0c;高度互联的工厂网络得以实现&#xff0c;远程监控和管理成为可能&#xff0c;…

鸿蒙应用模型:【Stage模型开发】概述

Stage模型开发概述 基本概念 下图展示了Stage模型中的基本概念。 图1 Stage模型概念图 [AbilityStage] 每个Entry类型或者Feature类型的HAP在运行期都有一个AbilityStage类实例&#xff0c;当HAP中的代码首次被加载到进程中的时候&#xff0c;系统会先创建AbilityStage实例…

微信网页版登录插件v1.1.1

说到如今的微信客户端&#xff0c;大家肯定会有很多提不完的意见或者建议。比如这几年体积越来越大&#xff0c;如果使用频率比较高&#xff0c;那占用空间就更离谱了。系统迷见过很多人电脑C盘空间爆满&#xff0c;都是由于微信PC版造成的。 而且&#xff0c;它还加了很多乱七…

【第8章】SpringBoot之单元测试

文章目录 前言一、准备1. 引入库2. 目录结构 二、测试代码1. SpringBoot3ApplicationTests2.测试结果 总结 前言 单元测试是SpringBoot项目的一大利器&#xff0c;在SpringBoot我们可以很轻松地测试我们的接口。 一、准备 1. 引入库 <dependency><groupId>org.s…

【JS基础知识07】函数

一&#xff1a;函数是什么以及函数作用 1 函数是什么 函数是经过封装、调用后&#xff0c;能够完成特定任务的代码块 2 函数的作用 仅需“函数名(实参)”就可以调用函数&#xff0c;起到精简代码&#xff0c;提高开发效率的作用 二&#xff1a;函数使用 1 语法规则&#…

Android 控件保持宽高比得几种方式

文章目录 Android 控件保持宽高比得几种方式adjustViewBounds百分比布局ConstraintLayout自定义View Android 控件保持宽高比得几种方式 adjustViewBounds 仅适用于 ImageView&#xff0c;保持横竖比。 <ImageViewandroid:layout_width"match_parent"android:l…

【使用ChatGPT构建应用程序】应用程序开发概述:1. 管理秘钥、2. 数据安全、3. 与应用程序解耦、4. 注意提示语的注入攻击

文章目录 一. 首先注意的两个方面1. 管理API密钥1.1. 用户提供API密钥1.2. 你自己提供API密钥 2. 数据安全和数据隐私 二. 软件架构设计原则&#xff1a;与应用程序解耦三. 注意LLM提示语的注入攻击1. 分析输入和输出2. 监控和审计3. 其他要注意的注入情况 在了解了ChatGPT的文…

SheetJS V0.17.5 导入 Excel 异常修复 Invalid HTML:could not find<table>

导入 Excel 提示错误&#xff1a;Invalid HTML:could not find<table> 检查源代码 发现 table 属性有回车符 Overview: https://docs.sheetjs.com/docs/ Source: https://git.sheetjs.com/sheetjs/sheetjs/issues The public-facing websites of SheetJS: sheetjs.com…

Linux静态库、共享动态库介绍、制作及使用

参考学习&#xff1a;Linux下的各种文件 、动态库基本原理和使用方法&#xff0c;-fPIC选项的来龙去脉 、Linux静态库和动态库分析 文章写作参考&#xff1a;Linux共享库、静态库、动态库详解 - sunsky303 - 博客园 (cnblogs.com) 一.Linux共享库、静态库、动态库详解 使用G…

2021CSP-J普及组复赛-第一题:分糖果

2021CSP-J普及组复赛 第一题&#xff1a; 题目&#xff1a; 输入&#xff1a; 7 16 23输出&#xff1a; 6思路&#xff1a; 这是一个简单的思考题&#xff0c;没有用到重要的算法 ①简单的思路即暴力方法就是利用for循环从L 到 R 遍历求出其中最大的奖励值&#xff0c;由于R…

全程曝光 计算机领域顶会投稿后会经历哪些关键环节?

会议之眼 快讯 亲爱的计算机领域大牛们&#xff0c;当你挥洒汗水&#xff0c;精心打磨一篇科研论文&#xff0c;终于怀着激动的心情投稿至顶会——&#xff08;如&#xff08;ACM MM 、ACL、AAAI&#xff09;时&#xff0c;你是否想知道接下来这篇论文会经历怎样的旅程&#x…

数据结构(1):线性表

1 线性表的顺序实现 创建的新项目是cpp类型哦&#xff01; 1.1 初始化 1.1.1 静态分配 #define _CRT_SECURE_NO_WARNINGS#include <stdio.h> #define MaxSize 10 //定义顺序表的长度 typedef struct {int data[MaxSize];//用静态的数组存放元素&#xff01;int lengt…

【错题集-编程题】小红取数(动态规划 - 01 背包 + 同余)

牛客对应题目链接&#xff1a;小红取数_牛客题霸_牛客网 (nowcoder.com) 一、分析题目 这道题是不能用空间优化的。 同余原理 a % k x 和 b % k y <> (ab) % k 0 <> (xy) % k 0 状态表示 dp[i][j]&#xff1a;表示从前 i 个数中挑选&#xff0c;总和 %k 等于 j…

一篇文章搞懂二叉树

文章目录 DP 树叶的度树的度节点的层次节点的祖先节点的子孙双亲节点或父节点 树的表示孩子兄弟表示法双亲表示法树和非树树的应用 二叉树满二叉树完全二叉树推论二叉树的存储以数组的方式以链表的方式堆(Heap)堆的分类大根堆和小根堆的作用 二叉树的遍历DFS和BFS DP 动态规划…

NVR对接三方相机预览黑屏问题案例

一、 问题现象 【问题现象】NVR接入三方相机,通道状态显示在线,但本地、web预览显示黑屏。更换H.264&#xff0c;H.265均预览黑屏&#xff0c;且NVR侧的萤石云手机APP预览报错260025。 【现场拓扑】现场拓扑如下 &#xff08;1&#xff09; IPC使用onvif协议添加至NVR&#xff…

Facebook的魅力:数字时代的社交热点

在当今数字化时代&#xff0c;社交媒体已经成为人们日常生活中不可或缺的一部分&#xff0c;而Facebook作为其中的巨头&#xff0c;一直以其独特的魅力吸引着全球数十亿用户。本文将深入探讨Facebook的魅力所在&#xff0c;以及它在数字时代的社交热点。 1. 社交网络的霸主&…

如何做好投入式水位计的安装与维护

投入式水位计是一种广泛应用于各种环境和水位监测场景的精确测量设备。为了确保其长期稳定运行和测量准确性&#xff0c;正确的安装和维护至关重要。本文将详细介绍投入式水位计的安装步骤和注意事项&#xff0c;以及维护过程中的关键要点。 一、投入式水位计的安装 准备工作&a…

JAVA类与方法·易错题分析

分析一下作业中关于类与方法写错或者易错的题。 N o . 1 No.1 No.1 下面程序的执行结果是______。 public class Test7 {public static void main(String[] args){new B().display();} } class A{public void draw() {System.out.print("Draw A.");}public void di…

基于STM32单片机老人体温心率血氧跌倒定位短信报警

一.硬件及设计功能 以STM32F103C8T6为中央处理器&#xff0c;GPS模块用采集数据&#xff0c;将数据发送给单片机后&#xff0c;单片机根据定位计算公式得出当前位置的经纬度信息和时间信息。经过LCD显示器处理后得出和时间信息SIM800模块发送短信到设定的手机号上&#xff0c;将…

软件系统测试的类型和方法介绍

测试是软件开发过程中至关重要的一环&#xff0c;负责验证和确认软件系统是否符合预期的需求&#xff0c;并帮助开发团队消除潜在的缺陷。系统测试作为软件测试中不可缺少的过程&#xff0c;是根据预先制定的测试计划和测试用例&#xff0c;以检查软件系统功能、性能、安全性和…