学习笔记|回顾(1-12节课)|应用模块化的编程|添加函数头|静态变量static|STC32G单片机视频开发教程(冲哥)|阶段小结:应用模块化的编程(上)

文章目录

  • 1.回顾(1-12节课)
  • 2.应用模块化的编程(.c + .h)
    • Tips:添加函数头
    • 创建程序文件三步
    • 引脚定义都在.h文件
    • 函数定义三步
    • bdata位寻址变量的使用
  • 3.工程文件编写
    • 静态变量static的使用
    • 完整程序为:
      • demo.c:
      • seg_led.c:
      • seg_led.h:

1.回顾(1-12节课)

一、认识单片机
二、了解单片机硬件(介绍开发板)
三、开发环境搭建和下载,新工程建立资料下载
四、点亮点一个LED(CDC和HID下载)		--GPIO
五、C语言运算符和进制数入门
六、LED闪烁和花式点灯       			--GPIO
七、按键点亮灯					--GPIO
八、蜂鸣器					--GPIO
九、数码管的静态使用				--GPIO
十、数码管动态点亮 				--GPIO
十一、定时器					--TIM
十二、计数器的使用				--TIM

重点理清程序的逻辑思路。重点理清程序的逻辑思路。重点理清程序的逻辑思路。什么时候打开LED?LED打开多久?什么时候切换数码管显示?什么时候按键按下触发什么功能?
之前的课主要是带大家熟悉写程序的方法,分析逻辑,实现我们要的功能。
那么这一节课开始,我们要规范程序,符合我们工程师级别的代码规范。

2.应用模块化的编程(.c + .h)

一、LED & 数码管 --led_seg.c, led_seg.h
二、按键 --key.c, key.h
三、蜂鸣器 --beep.c, beep.h
四、定时器 --tim.c, tim.h
一个功能对应一个.c和.h

Tips:添加函数头

//========================================================================
// 函数名称:
// 函数功能:
// 入口参数: @
// 函数返回:
// 当前版本: VER1.0
// 修改日期: 2023
// 当前作者:
// 其他备注:
//========================================================================
在keil中设置:
在这里插入图片描述

在这里插入图片描述
添加后,重启软件就可以使用了。

创建程序文件三步

新建文件并保存
添加到工程
添加引用路径

引脚定义都在.h文件

sbit 名称 = P10;
#define 名称 P10

函数定义三步

定义
声明
调用

修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。
举例1:如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。
举例2:如果文件a.c需要引用b.c中变量int v,就可以在b.h中声明extern int v,然后a.c调用b.h就可以引用变量v。
注意extern修饰的变量不能赋初值。
详细介绍可参考:extern关键字,C语言extern关键字用法详解。

bdata位寻址变量的使用

a.c a.h
u8 bdata LED = 0x00; extern u8 bdata LED;
sbit LED0 = LED^0; extern bit LED0;
sbit LED1 = LED^1; extern bit LED1;

3.工程文件编写

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

在这里插入图片描述
因为他们公用P6端口,所以给他们放在了一个文件。

之前的程序是在定时器中通过一个函数刷新数码管,现在就要给他增加刷新LED的功能。这里刷新显示,在别的地方赋值。
利用上节的文件,复制成工程9.TIM多任务,进入,新建目录(路径)HARDWARE,所有子程序都放入,本次要写的4个功能分别建立4个文件夹,留着备用:
在这里插入图片描述
打开project,选择Add New ltem to Group ‘source Group 1’…
在这里插入图片描述

就可以在LED目录中新建seg_led.c和seg_led.h:
在这里插入图片描述

添加引用路径:
在这里插入图片描述

至此,工程文件模板就建立了。
seg_led.h修改,添加infdef预定义:

#ifndef __SEG_LED_H
#define __SEG_LED_H#include "COMM/stc.h"		//调用头文件
#include "COMM/usb.h"#endif

可以将此预定义存为template,方便使用。
在seg_led.c和demo.c中都增加对seg_led.h的调用。
将demo.c中数码管的功能移植至seg_led.c中:

u8 SEG_Tab[21] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff};	//共21个字节:0-9段码共10个,0-9带小数点共10个,全部不显示共1个,
u8 COM_Tab[8] = { 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe };																	//0-7的位码数组
u8 Show_Tab[8] = {20,20,20,20,20,20,20,20};

静态变量static的使用

如果要在其他文件中控制变量Show_Tab用于显示,则需要将其放在.h文件中作为外部变量:extern u8 Show_Tab[8];,之后就可以在主函数里调用。
移植void SEG_Fre(void)函数至seg_led.c,并在函数体中增加static 变量,静态变量,只有第一次执行的时候再赋初始值,定义:static int num = 0;,后面不再赋值。
如果不加static,每次进入函数后都会重新赋为0 ,不会刷新第2位以后的值,故需要使用静态变量,只赋值一次。
需要在seg_led.h中声明一下:void SEG_Fre(void);
删除或注释掉demo.c中原程序代码的计数器初始化部分:

//	TMOD = 0x50;			//设置计数器模式   
//	TL1 = 0x00;				//设置计数初始值
//	TH1 = 0x00;				//设置计数初始值
//	TF1 = 0;				//清除TF1标志
//	TR1 = 1;				//定时器1开始计时
//	ET1 = 1;				//使能定时器1中断
//	    
//	P3PU = 0x20; 			//打开内部上拉4.1K

删除主函数中冗余代码,留定时器0初始化。
在主程序demo.c文件中加入数码管赋初值。

	//数码管初始化,显示0-7:Show_Tab[0] = 0;Show_Tab[1] = 1;Show_Tab[2] = 2;Show_Tab[3] = 3;Show_Tab[4] = 4;Show_Tab[5] = 5;Show_Tab[6] = 6;Show_Tab[7] = 7;

在.h文件中增加引脚定义:

//------------------------引脚定义------------------------//
#define SEG_SEG P6
#define SEG_COM P7
#define LED_POW P40 	//P40是led的电源开关

编译,选目标文件,下载完成,数码管显示0-7,但led还是不亮,需要加入相应点亮刷新代码。
seg_led.h中定义LED的显示变量和电源开关:

extern u8 LED_DATA;		//LED的显示变量#define LED_POW P40 	//P40是led的电源开关

增加引脚定义:
seg_led.c中更新刷新函数SEG_Fre:

void SEG_Fre( void )
{static int num = 0;if(num <=7 )						//num==0-7的执行{LED_POW = 0;					//关闭LED电源SEG_COM = COM_Tab[num];			//相应数码管位码的选择SEG_SEG = SEG_Tab[Show_Tab[num]];//需要显示的数字的内码}else if ( num <= 8 )				//num==8的执行{LED_POW = 0;					//LED刷新,打开电源SEG_COM = 0xff;					//关闭数码管SEG_SEG = LED_DATA;				//输出LED状态}else								//num==9的执行{LED_POW = 1;					//LED关闭电源SEG_COM = 0xff;					//关闭数码管SEG_SEG = 0xff;					//关闭所有段码信号}num++;if( num >=10 )num = 0;						//num清零
}

demo.c中对LED赋初值:

LED_DATA = 0x0f;	//赋初值,亮一半灭一半

完整程序为:

demo.c:

#include "COMM/stc.h"		//调用头文件
#include "COMM/usb.h"
#include "seg_led.h"#define KEY1 P32		//定义一个按键 引脚选择P32
#define KEY2 P33		//定义一个按键 引脚选择P33#define BEEP P54		//定义一个按键 引脚选择P54#define SEG_Delay  1	//延时多少ms#define MAIN_Fosc 24000000UL	//定义主时钟char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";u32 TimCount = 0;		//计数单位1ms
bit RUN_State = 0;		//开始运行/结束运行
u8 num = 0;
u16 Count_T1 = 0;void sys_init();	//函数声明
//void delay_ms(u16 ms);	//unsigned int
//void INT1_Isr(void);
void Timer0_Isr(void);void main()					//程序开始运行的入口
{sys_init();				//USB功能+IO口初始化usb_init();				//usb库初始化EA = 1;					//CPU开放中断,打开总中断。//数码管初始化,显示0-7:Show_Tab[0] = 0;Show_Tab[1] = 1;Show_Tab[2] = 2;Show_Tab[3] = 3;Show_Tab[4] = 4;Show_Tab[5] = 5;Show_Tab[6] = 6;Show_Tab[0] = 7;LED_DATA = 0x0f;	//赋初值,亮一半灭一半while(1)		//死循环{if( DeviceState != DEVSTATE_CONFIGURED ) 	//continue;if( bUsbOutReady ){usb_OUT_done();}}
}void sys_init()		//函数定义
{WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快EAXFR = 1; //扩展寄存器(XFR)访问使能CKCON = 0; //提高访问XRAM速度P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口P3M0 = 0x00;P3M1 = 0x00;P3M0 &= ~0x03;P3M1 |= 0x03;//设置USB使用的时钟源IRC48MCR = 0x80;    //使能内部48M高速IRCwhile (!(IRC48MCR & 0x01));  //等待时钟稳定USBCLK = 0x00;	//使用CDC功能需要使用这两行,HID功能禁用这两行。USBCON = 0x90;
}//void delay_ms(u16 ms)	//unsigned int
//{
//	u16 i;
//	do
//	{
//		i = MAIN_Fosc/6000;
//		while(--i);
//	}while(--ms);
//}void Timer0_Isr(void) interrupt 1 //1ms进来执行一次,无需其他延时,重复赋值
{SEG_Fre();		//数码管刷新1ms执行一次}//void INT1_Isr(void) interrupt 3 //计时器中断
//{
//	//P60 = !P60; //led取反
//}

seg_led.c:

#include "seg_led.h"u8 SEG_Tab[21] = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff};	//共21个字节:0-9段码共10个,0-9带小数点共10个,全部不显示共1个,
u8 COM_Tab[8]  = { 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe };																	//0-7的位码数组
u8 Show_Tab[8] = {20,20,20,20,20,20,20,20}; 																					//数码管显示数组,上电后,全部关闭显示
//u8 LED_DATA  =  0xff;																											//LED初始全部熄灭void SEG_Fre( void )
{static int num = 0;if(num <=7 )						//num==0-7的执行{LED_POW = 0;					//关闭LED电源SEG_COM = COM_Tab[num];			//相应数码管位码的选择SEG_SEG = SEG_Tab[Show_Tab[num]];//需要显示的数字的内码}else if ( num <= 8 )				//num==8的执行{LED_POW = 0;					//LED刷新,打开电源SEG_COM = 0xff;					//关闭数码管SEG_SEG = LED_DATA;				//输出LED状态}else								//num==9的执行{LED_POW = 1;					//LED关闭电源SEG_COM = 0xff;					//关闭数码管SEG_SEG = 0xff;					//关闭所有段码信号}num++;if( num >=10 )num = 0;						//num清零
}

seg_led.h:

#ifndef __SEG_LED_H
#define __SEG_LED_H#include "COMM/stc.h"		//调用头文件
#include "COMM/usb.h"extern u8 Show_Tab[8];		//数码管的内码显示变量
extern u8 LED_DATA;		//LED的显示变量//------------------------引脚定义------------------------//
#define SEG_SEG P6
#define SEG_COM P7
#define LED_POW P40 	//P40是led的电源开关void SEG_Fre(void);  		//仅声明#endif

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker系列(3) - 常用软件安装

文章目录 3. docker安装常用软件3.1 安装nginx3.2 安装redis3.3 安装mysql3.4 部署springboot程序3.4.1 编写dockerfile3.4.2 构建镜像3.4.3 启动镜像 3. docker安装常用软件 3.1 安装nginx docker pull nginx#挂载启动 docker run -it -d \ --namenginx \ --networkpub_netw…

【计算机网络】什么是WebSocket?

目录 WebSocket简介协议优点使用场景 WebSocket WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信&#xff0c;位于OSI模型的应用层。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务器主动向客户端推送数据。在WebSocket API中&a…

Leecode1160: 拼写单词

直接使用一个哈希表存整体的结果&#xff0c;一个临时的哈希表每次算一遍&#xff0c;但是1是要设置标志位来判断最后是否正确并加上长度&#xff0c;2是千万要记得每次新建一个空间来存哈希表绝对不能不空间就等于&#xff0c;会出事&#xff01;&#xff01;

Copymonkey:AI生成营销广告文案

【产品介绍】 CopyMonkey.ai 是一家成立于2021年的创新型人工智能&#xff08;AI&#xff09;初创企业&#xff0c;专注于开发一款强大的AI写作助手。我们的产品旨在帮助用户以更高效且更自然的方式创作各种文本内容&#xff0c;无论是文章、博客、电子邮件、简历还是其他类型的…

Sketch for mac v98.2最新版 修复了打开某些文档时导致 Sketch 崩溃的错误

Sketch是一款专为Mac操作系统设计的矢量图形编辑软件&#xff0c;被广泛应用于UI/UX设计、网页设计、移动应用设计等领域。Sketch提供了各种工具和功能&#xff0c;包括绘图、图形设计、排版等&#xff0c;可以帮助设计师轻松地创建高质量的矢量图形和模型。 Sketch for mac更…

AIGC:【LLM(八)】——Baichuan2技术报告

文章目录 摘要1. 引言2. 预训练2.1 预训练数据&#xff08;Pre-training Data&#xff09;2.2 架构&#xff08;Architecture&#xff09;2.3 令牌化器&#xff08;Tokenizer&#xff09;2.3.1 Positional Embeddings 2.4 激活和规范化&#xff08;Activations and Normalizati…

巨人互动|Facebook海外户Facebook风控规则有什么

Facebook是全球最大的社交媒体平台之一&#xff0c;每天有数十亿的用户在其上发布、分享和交流各种内容。为了维护平台的安全性和用户体验&#xff0c;Facebook制定了严格的风控规则来监测和处理违规行为。下面小编讲讲Facebook风控规则。 巨人互动|Google海外户&Google Ad…

Ubuntu不能上网解决办法

问题及现象 Ubuntu的虚拟机&#xff08;18.04&#xff09;总是莫名就不能上网了。 使用ifconfig -a 查看&#xff0c;ensxx&#xff08;xx为虚拟机分配的id号&#xff09;对应的网卡有mac地址&#xff0c;但是没有分配ip地址。 Network中也没有Wired的选项。 临时解决方案 使…

一阶微分方程

目录 可分离变量的方程 齐次微分方程 一阶线性微分方程 伯努科方程 全微分方程 可分离变量的方程 可分离变量的方程是一种常见的一阶常微分方程类型&#xff0c;其特点是可以通过将变量分离到方程的两侧&#xff0c;从而可以分别对各自变量进行积分。一般形式的可分离变量…

ElasticSearch系列-简介与安装详解

全文检索 讲ElasticSearch之前, 需要先提一下全文检索.全文检索是计算机程序通过扫描文章中的每一个词&#xff0c;对每一个词建立一个索引&#xff0c;指明该词在文章中出现的次数和位置。当用户查询时根据建立的索引查找&#xff0c;类似于通过字典的检索字表查字的过程。 …

文本直接生成20多种背景音乐,免费版Stable Audio来了!

9月14日&#xff0c;著名开源平台Stability AI在官网发布了&#xff0c;音频生成式AI产品Stable Audio。&#xff08;免费使用地址&#xff1a;https://www.stableaudio.com/generate&#xff09; 用户通过文本提示就能直接生成摇滚、爵士、电子、嘻哈、重金属、民谣、流行、朋…

天线原理【1】 天线辐射的物理过程

1 前言 前面讲以振子方程入手分析电磁场问题的解的时候&#xff0c;有网友发信息说这和天线有什么关系&#xff0c;怎么从振子入手分析天线&#xff1b; 那我就开始写几次关于天线的。 有一种说法是&#xff0c;能给任何人讲懂的理论&#xff0c;才说明你真的懂了。 对天线部…

地理地形sdk:Tatuk GIS Developer Kernel for .NET Crack

Tatuk GIS Developer Kernel for .NET 是一个变体&#xff0c;它是受控代码和 .NET GIS SDK&#xff0c;用于为用户 Windows 操作系统创建专业 GIS 软件的过程。它被认为是一个完全针对Win Forms 的.NET CIL&#xff0c;WPF 框架是针对C# 以及VB.NET、VC、Oxy 以及最终与.NET 的…

分布式文件系统对比与选型参考

目录 一、分布式文件系统 1、 数据的存储方式&#xff1a; 2、 数据的读取速率 3、 数据的安全机制 二、主流分布式文件系统介绍 1. GFS&#xff08;Google File System&#xff09; 2. HDFS&#xff08;Hadoop Distributed File System&#xff09; 3. Ceph …

流程模型相关的数据库表-流程模型相关的数据迁移

1、流程定义数据表&#xff08;act_re_procdef&#xff09; 业务流程定义数据表。此表和 ACT_RE_DEPLOYMENT 是多对一的关系&#xff0c;即&#xff0c;一个部署的bar包里可能包含多个流程定义文件&#xff0c;每个流程定义文件都会有一条记录在 ACT_REPROCDEF 表内&#xff0…

TypeScript类型兼容:结构化类型

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 1. 鸭子类型&#xff1a;定义和示例 2. 鸭子类型的优点 2.1 代码的灵活性 2.2 代码的复用 2.3 与 JavaScript 的…

PostgreSQL 入门

文章目录 PostgreSQL介绍PostgreSQL和MySQL的区别PostgreSQL的安装PostgreSQL的配置远程连接配置配置数据库的日志 PostgreSQL基本操作用户操作权限操作 图形化界面安装总结 PostgreSQL介绍 PostgreSQL是一个功能强大的 开源 的关系型数据库&#xff0c;底层基于C实现。其开源…

【推荐】SpringMVC与JSON数据返回及异常处理机制的使用

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《【推荐】Spring与Mybatis集成整合》 ⛺️ 生活的理想&#xff0c;为了不断更新自己 ! 1.JSON 在SpringMVC中&#xff0c;JSON数据返回通常是通过使用ResponseBody注解将Java对象转换为JSO…

2023 年最新 Docker 容器技术基础详细教程(更新中)

Docker 基本概述 Docker 是一个开源的应用容器引擎&#xff0c;它让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Linux 或 Windows 操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间…

CUDA小白 - NPP(8) 图像处理 Morphological Operations

cuda小白 原始API链接 NPP GPU架构近些年也有不少的变化&#xff0c;具体的可以参考别的博主的介绍&#xff0c;都比较详细。还有一些cuda中的专有名词的含义&#xff0c;可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus&#xf…