找回密码
 立即注册
楼主: zhangshiwei

关于32位8051实验箱-STC32G12K128学习记录

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-19 17:56:45 | 显示全部楼层
本帖最后由 zhangshiwei 于 2024-6-25 18:04 编辑

2024.06.19

第八集
学习心得:蜂鸣器的使用
(1)认识蜂鸣器,了解蜂鸣器的结构
常见的蜂鸣器分为了有源蜂鸣器和无源蜂鸣器,如何区分有源和无源(内部是否带有震荡源)
截图202406191746433432.jpg
蜂鸣器的原理蜂鸣器的工作原理主要涉及电磁式和压电式两种类型。电磁式蜂鸣器的工作原理与扬声器相似,通过磁铁和电磁线圈的相互作用带动振动膜片产生声波。当电流通过线圈时,会在磁场中产生力,从而使膜片振动,进而发出声音。压电式蜂鸣器则是利用压电材料的逆压电效应,当压电材料和金属片两端施加上一个电压后,蜂鸣片就会产生机械变形而发出声响。
蜂鸣器按其驱动方式的不同可分为有源蜂鸣器和无源蜂鸣器。有源蜂鸣器内含驱动电路,接上合适的电压就能持续发出声音,不同的音频驱动电路可以发出不同的声音。无源蜂鸣器则需要外部加一个音频振荡电路才能连续发出声音,因此也被称为他激式蜂鸣器。
在具体应用中,无源蜂鸣器的驱动方式可以通过PWM(脉冲宽度调制)控制固定频率的蜂鸣器,通过对PWM输出波形进行设置,可以调整蜂鸣器的波形周期和占空比,从而实现不同频率和音调的声音输出。另外,也可以通过I/O口定时翻转电平来驱动蜂鸣器,通过设定定时器的预分频和载入/计数寄存器的值,可以产生特定周期和占空比的方波信号,从而驱动无源蜂鸣器发出声音。
有源蜂鸣器我们直接给通电之后,蜂鸣器就会发出声音。


蜂鸣器的发声原理由振动装置和谐振装置组成,而蜂鸣器又分为无源他激型与有源自激型。
       无源他激型蜂鸣器的工作发声原理是:方波信号输入谐振装置转换为声音信号输出,无源他激型蜂鸣器的工作发声原理图
截图202406251803045240.jpg
有源自激型蜂鸣器的工作发声原理是:直流电源输入经过振荡系统的放大取样电路在谐振装置作用下产生声音信号,有源自激型蜂鸣器的工作发声原理图
截图202406251803498166.jpg


(2)如何控制蜂鸣器,熟悉蜂鸣器的控制原理
截图202406191749464577.jpg

程序的设计
截图202406191751251569.jpg

(3)关于蜂鸣器的实战训练
截图202406191751546708.jpg

程序设计思路
截图202406191753379228.jpg

总结:通过本节课了解了蜂鸣器的使用方法,然后如何去驱动蜂鸣器,在程序上如何设计驱动蜂鸣器的架构。
截图202406191756222637.jpg




回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-19 17:58:45 | 显示全部楼层
2024.06.19

第八集
学习心得:蜂鸣器的使用
(1)认识蜂鸣器,了解蜂鸣器的结构
常见的蜂鸣器分为了有源蜂鸣器和无源蜂鸣器,如何区分有源和无源(内部是否带有震荡源)


有源蜂鸣器我们直接给通电之后,蜂鸣器就会发出声音。
(2)如何控制蜂鸣器,熟悉蜂鸣器的控制原理


程序的设计


(3)关于蜂鸣器的实战训练


程序设计思路


总结:通过本节课了解了蜂鸣器的使用方法,然后如何去驱动蜂鸣器,在程序上如何设计驱动蜂鸣器的架构。

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-19 18:00:08 | 显示全部楼层
2024.06.19

第八集
学习心得:蜂鸣器的使用
(1)认识蜂鸣器,了解蜂鸣器的结构
常见的蜂鸣器分为了有源蜂鸣器和无源蜂鸣器,如何区分有源和无源(内部是否带有震荡源)


有源蜂鸣器我们直接给通电之后,蜂鸣器就会发出声音。
(2)如何控制蜂鸣器,熟悉蜂鸣器的控制原理


程序的设计


(3)关于蜂鸣器的实战训练


程序设计思路


总结:通过本节课了解了蜂鸣器的使用方法,然后如何去驱动蜂鸣器,在程序上如何设计驱动蜂鸣器的架构。


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-19 18:14:25 | 显示全部楼层
本帖最后由 zhangshiwei 于 2024-6-25 18:07 编辑

2024.06.19

第九集
学习心得:数码管的静态使用
(1)认识数码管
开发板上面使用的是4位数码管,数码管的定义(LED数码管),一般是类似于1个“8”为1位数码管
截图202406191802267015.jpg
数码管,也称作辉光管,是一种可以显示数字和其他信息的电子设备。玻璃管中包括一个金属丝网制成的阳极和多个阴极。大部分数码管阴极的形状为数字。管中充以低压气体,通常大部分为加上一些和/或。给某一个阴极充电,数码管就会发出颜色光,视乎管内的气体而定,一般都是橙色或绿色。

数码管分为了共阳极和共阴极的形式
按发光二极管单元连接方式可分为共阳极数码管共阴极数码管。共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。
截图202406191807188930.jpg

LED数码管(LED Segment Displays)是由多个发光二极管封装在一起组成。
8”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。led数码管常用段数一般为7段有的另加一个小数点,还有一种是类似于3位“+1”型。位数有半位,1,2,3,4,5,6,8,10位等等,led数码管根据LED的接法不同分为共阴和共阳两类,了解LED的这些特性,对编程是很重要的,因为不同类型的数码管,除了它们的硬件电路有差异外,编程方法也是不同的。图2是共阴和共阳极数码管的内部电路,它们的发光原理是一样的,只是它们的电源极性不同而已。颜色有红,绿,蓝,黄等几种。led数码管广泛用于仪表,时钟,车站,家电等场合。选用时要注意产品尺寸颜色,功耗,亮度,波长等。
数码管内部连接图
截图202406191808035733.jpg

(2)了解相关的控制原理
截图202406191809184624.jpg

程序设计
截图202406191810416950.jpg
数码管要正常显示,就要用驱动电路来驱动数码管的各个段码,从而显示出我们要的数字,因此根据数码管的驱动方式的不同,可以分为静态式和动态式两类。
静态显示驱动
静态驱动也称直流驱动。静态驱动是指每个数码管的每一个段码都由一个单片机I/O端口进行驱动,或者使用如BCD码二-十进制译码器译码进行驱动。静态驱动的优点是编程简单,显示亮度高,缺点是占用I/O端口多,如驱动5个数码管静态显示则需要5×8=40根I/O端口来驱动,要知道一个89S51单片机可用的I/O端口才32个,实际应用时必须增加译码驱动器进行驱动,增加了硬件电路的复杂性。


(3)使用数码管实现0-9的显示
总结:了解了数码管的数字内码由来,学会数码管通过数组方式获取数值,同时根据数码管显示0-9的项目,然后数码管显示字母;另外通过一个按键设置数码管驱动0-9数码管循坏,按下另外一个按键显示对应的数字,并且蜂鸣器发出响声。

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-19 18:30:57 | 显示全部楼层
本帖最后由 zhangshiwei 于 2024-6-25 18:12 编辑

2024.06.19

第十集
学习心得:数码管的动态显示
(1)熟悉并掌握数码管动态刷新的原理,熟悉如何设计实现4位数码管分别点亮“1、2、3、4”的程序;
截图202406191816418862.jpg
动态显示驱动
数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,
位选通由各自独立的I/O线控制,当单片机输出字形码时,所有数码管都接收到相同的字形码,但究竟是哪个数码管会显示出字形,取决于单片机对位选通COM端电路的控制,
所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。
在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,
给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。

[size=1.2em]

[size=1.2em]数码管驱动方式分类

动态数码管驱动方式:扫描方式
共阴数码管扫描:一个低电平其他全部为高电平,循环变换
共阳数码管扫描:一个高电平其他全部为低电平,循环变换

数码管代码示例
头文件
  1. #ifndef __QYQ_MODULE_SMG_H_
  2. #define __QYQ_MODULE_SMG_H_
  3. #include "chip_include.h"
  4. #ifdef __QYQ_MODULE_SMG_C_
  5. #define QYQ_MODULE_SMG_EXT extern
  6. #else
  7. #define QYQ_MODULE_SMG_EXT
  8. #endif
  9. typedef struct
  10. {
  11.     void (*qyq_module_smg_config_writedat)(uint8_t dat);   // 写数据
  12.     void (*qyq_module_smg_config_writeaddr)(uint8_t addr); // 写地址,从0编号开始写
  13.     void (*qyq_module_smg_config_delay)(void);             // 如果采用系统延迟,不需要适配延迟函数,否则需要延迟函数
  14.     uint8_t qyq_module_smg_number;                         // 数码管数量
  15.     uint8_t qyq_module_smg_off_value;                      // 数码管全部关闭值
  16.     uint8_t qyq_module_smg_data_count;                     // 数码管计数器
  17.     uint8_t *qyq_module_smg_data_value;                    // 数码管显示buf
  18. } qyq_module_smg_config_t;
  19. // 功能
  20. typedef struct qyq_module_smg_type
  21. {
  22.     qyq_module_smg_config_t *qyq_module_smg_config;
  23.     int8_t (*qyq_module_smg_write)(struct qyq_module_smg_type *this, uint8_t smg_id, uint8_t value);
  24.     int8_t (*qyq_module_smg_scan)(struct qyq_module_smg_type *this);
  25. } qyq_module_smg_type_t;
  26. QYQ_MODULE_SMG_EXT int8_t qyq_module_smg_create(qyq_module_smg_type_t *this, qyq_module_smg_config_t *qyq_module_smg_config);
  27. #endif
复制代码
源文件
  1. #define __QYQ_MODULE_SMG_C_
  2. #include "qyq_module_smg.h"
  3. static uint8_t qyq_module_smg_font[][2] = {
  4.     {0xFF, 0},
  5.     {'0', 0x3F}, //"0"
  6.     {'1', 0x06}, //"1"
  7.     {'2', 0x5B}, //"2"
  8.     {'3', 0x4F}, //"3"
  9.     {'4', 0x66}, //"4"
  10.     {'5', 0x6D}, //"5"
  11.     {'6', 0x7D}, //"6"
  12.     {'7', 0x07}, //"7"
  13.     {'8', 0x7F}, //"8"
  14.     {'9', 0x6F}, //"9"
  15.     {'A', 0x77}, //"A"
  16.     {'B', 0x7C}, //"B"
  17.     {'C', 0x39}, //"C"
  18.     {'D', 0x5E}, //"D"
  19.     {'E', 0x79}, //"E"
  20.     {'F', 0x71}, //"F"
  21.     {'H', 0x76}, //"H"
  22.     {'L', 0x38}, //"L"
  23.     {'n', 0x37}, //"n"
  24.     {'U', 0x3E}, //"u"
  25.     {'P', 0x73}, //"P"
  26.     {'O', 0x5C}, //"o"
  27.     {'-', 0x40}, //"-"
  28. };
  29. static uint8_t qyq_module_smg_getfont(uint8_t value)
  30. {
  31.     uint8_t i = 0;
  32.     for (i = 0; i < sizeof(qyq_module_smg_font) / 2; i++)
  33.     {
  34.         if (value == qyq_module_smg_font[i][0])
  35.         {
  36.             return i;
  37.         }
  38.     }
  39.     return 0;
  40. }
  41. static int8_t qyq_module_smg_scan(qyq_module_smg_type_t *this)
  42. {
  43.     if (this == null)
  44.     {
  45.         return -1;
  46.     }
  47.     this->qyq_module_smg_config->qyq_module_smg_config_writedat(this->qyq_module_smg_config->qyq_module_smg_off_value);
  48.     this->qyq_module_smg_config->qyq_module_smg_config_writeaddr(this->qyq_module_smg_config->qyq_module_smg_data_count);
  49.     this->qyq_module_smg_config->qyq_module_smg_config_writedat(qyq_module_smg_font[qyq_module_smg_getfont(this->qyq_module_smg_config->qyq_module_smg_data_value[this->qyq_module_smg_config->qyq_module_smg_data_count])][1]);
  50.     if (this->qyq_module_smg_config->qyq_module_smg_config_delay != null)
  51.     {
  52.         this->qyq_module_smg_config->qyq_module_smg_config_delay();
  53.     }
  54.     this->qyq_module_smg_config->qyq_module_smg_data_count++;
  55.     if (this->qyq_module_smg_config->qyq_module_smg_data_count >= this->qyq_module_smg_config->qyq_module_smg_number)
  56.     {
  57.         this->qyq_module_smg_config->qyq_module_smg_data_count = 0;
  58.     }
  59.     return 0;
  60. }
  61. static int8_t qyq_module_smg_write(qyq_module_smg_type_t *this, uint8_t smg_id, uint8_t value)
  62. {
  63.     if (this == null)
  64.     {
  65.         return -1;
  66.     }
  67.     this->qyq_module_smg_config->qyq_module_smg_data_value[smg_id] = value;
  68.     return 0;
  69. }
  70. int8_t qyq_module_smg_create(qyq_module_smg_type_t *this, qyq_module_smg_config_t *qyq_module_smg_config)
  71. {
  72.     if (this == null)
  73.     {
  74.         return -1;
  75.     }
  76.     if (qyq_module_smg_config == null)
  77.     {
  78.         return -1;
  79.     }
  80.     this->qyq_module_smg_config = qyq_module_smg_config;
  81.     this->qyq_module_smg_config->qyq_module_smg_data_count = 0;
  82.     qyq_module_smg_font[0][1] = this->qyq_module_smg_config->qyq_module_smg_off_value;
  83.     this->qyq_module_smg_scan = qyq_module_smg_scan;
  84.     this->qyq_module_smg_write = qyq_module_smg_write;
  85.     return 0;
  86. }
复制代码

(2)数码管驱动的控制原理
需要注意数码管驱动的方式,并且注意延时的设计,一般是给定1ms的延时,并且需要保证结束一个循环不能大于20ms,根据人的视觉暂留效应(也就是说人的视觉不容易分辨出50Hz以上的动态刷新);
截图202406191820391302.jpg

(3)如何同时点亮8位数码管
截图202406191823251021.jpg

针对数码管显示的对应数值确定,即段码
截图202406191824132570.jpg

程序设计思路
截图202406191825256987.jpg
什么是段选、什么是位选?

段选 就是 数码管各个发光二极管显示的段 组成的字

位选 就是 公共端引出的引脚,选择哪个数码管来显示

共阴、共阳 0~F 的段选显示

共阴数码管亮

0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d,

0        1         2       3        4       5

0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c,

6          7       8       9        A      B

0x39, 0x5e, 0x79, 0x71, 0x00,

C         D      E          F     无显示

共阳数码管亮

0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92,

0           1        2        3        4       5

0x82, 0xF8, 0x80, 0x90, 0x88, 0x83,

6           7        8        9        A       B

0xC6, 0xA1, 0x86, 0x8E, 0xFF,

C          D        E        F     无显示

消影

用人眼余晖,延时来 让人感觉数码管动态显示

总结:了解了数码管如何实现动态的显示,学会每一位的数码管的任意内容的显示;如何实现数码管的动态显示,程序上去设计如何驱动数码管。

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-20 18:42:20 | 显示全部楼层
本帖最后由 zhangshiwei 于 2024-6-25 18:19 编辑

2024.06.20
第十一集
学习心得:关于定时器的使用
(1)关于定时器的作用和意义
  1. while (1)
  2. {
  3. TimeCount++;
  4. delay_ms(1);
  5. }
复制代码

通过while函数在不断循环执行的时候,然后让程序设置的变量每间隔1ms能够自动加一,并且不会受到while循环的影响

截图202406200913103822.jpg
了解关于中断请求、中断响应、中断返回等基本的概述。熟悉关于定时器的定义(也就是定时器与计数器的统称)
截图202406200917382860.jpg
单片机定时器的概念
[color=var(--cos-color-text-link)]单片机定时器是一个电子元件,与[color=var(--cos-color-text-link)]计数器类似,但功能有所不同。计数器记录的是单片机外部的情况,接收外部脉冲,而定时器则由单片机自身提供一个非常稳定的计数器,这个稳定的计数器与单片机上连接的[color=var(--cos-color-text-link)]晶振部件相关。单片机定时器可以分为几种类型:

  • [color=var(--cos-color-text-link)]软件定时器:通过执行空指令达到延时的效果,但这种方法占用[color=var(--cos-color-text-link)]CPU时间,降低了CPU的利用率。
  • [color=var(--cos-color-text-link)]不可编程硬件定时器:通过基本电路和外接定时部件(如电阻和电容)完成定时功能,一旦设置后不能通过软件修改,优点是不需要占用CPU时间。
  • [color=var(--cos-color-text-link)]可编程定时器:通过软件确定定时值及其范围,功能强大且灵活性高。

实现定时功能的方法除了利用单片机内部的定时/计数器外,还包括软件定时、采用时基电路定时和采用可编程芯片定时。软件定时不占用硬件资源但占用CPU时间,而可编程芯片定时则易于用软件确定和修改定时值及范围,提供强大的定时功能和使用灵活性。

在单片机中,定时器和计数器实际上是同一个物理电子元件,只是应用场景不同。定时器用于测量时间间隔或产生周期性的中断请求,而计数器则用于对外部信号进行计数。8051系列单片机有两个定时器T0和T1,分别由特殊功能寄存器TH0/TL0和[color=var(--cos-color-text-link)]TH1/TL1构成,用于实现时间控制、延时、对外部时间计数和检测等场合。这些定时器和计数器的结构和功能使得单片机能够广泛应用于各种需要精确时间和事件控制的系统中。




(2)STC32G单片机定时器的使用原理
设置STC32G系列单片机内部的资源,主要是包含有5个24位定时器/计数器(8位预分频+16位计数)。定时器主要有T0-T4总计5个16位的定时器;内部核心就是一个加法计数器,本质就是对脉冲进行计数,以及关于设置定时方式(计数脉冲来自系统时钟)与计数方式(计数脉冲来自单片机外部引脚)的方法。
了解关于在定时器模式下,设置不分频或者12分频的方法,关于辅助寄存器AUXR的配置方法。
截图202406200927111462.jpg
定时器0/1模式寄存器(TMOD)的配置方法熟悉和操作
截图202406200931151368.jpg

定时器的工作模式熟悉与常用的额配置
截图202406200932154164.jpg

定时器的设置(定时器0/1控制寄存器TCON)的熟悉和操作。
(3)定时器的简单应用
截图202406201838275123.jpg 截图202406201839047868.jpg
定时器代码:
  1. while(1)
  2. {
  3.     TimeCount++;
  4.     delay_ms(1);
  5.     if (KEY1 == 0)
  6.                 {
  7.                         delay_ms(10);
  8.                         if (KEY1 == 0)
  9.                         {
  10.                                 while(KEY1 == 0);
  11.             }
  12.         }
  13. }
复制代码

总结:了解了定时器和定时器的中断概念;了解了如何使用定时器,关于使用工具对定时器的操作等等。


定时器中断
定时一定时间之后产生的中断,也就是定时器中断。
主程序:你在背书
中断:妈妈让你五分钟以后看一下锅里的汤有没有烧干,一个定时器中断的一个例子。

定时器是定时器和计数器的统称。
1)设置为定时器时,可实现硬件计时,或者使程序每隔一固定时间完成一项操作;
2)设置为计数器时候能够对脉冲进行计数;
3)替代长时间的delay,提高CPU的运行效率和处理速度,能及时的响应某个事件。


定时时间:
截图202406251817569057.jpg


定时器快速使用的方法:
STC-ISP有专用的定时器时间计算选项卡:

截图202406251818278615.jpg

输入参数后,生产C代码:

  1. void Timer0_Isr(void) interrupt 1
  2. {
  3. }
  4. void Timer0_Init(void)                //1000微秒@24.000MHz
  5. {
  6.         AUXR &= 0x7F;                        //定时器时钟12T模式
  7.         TMOD &= 0xF0;                        //设置定时器模式
  8.         TL0 = 0x30;                                //设置定时初始值
  9.         TH0 = 0xF8;                                //设置定时初始值
  10.         TF0 = 0;                                //清除TF0标志
  11.         TR0 = 1;                                //定时器0开始计时
  12.         ET0 = 1;                                //使能定时器0中断
  13. }
复制代码


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-20 18:51:53 | 显示全部楼层
本帖最后由 zhangshiwei 于 2024-6-25 18:23 编辑

2024.06.20
第十二集
学习心得:关于计数器的使用
(1)计数器的用途
关于计数器的用途,以及一些基本的应用,例如常见的编码器,其作用也是输出对应的脉冲;
截图202406201846307859.jpg
定时器介绍

在介绍定时器之前我们先科普下几个知识:

(1)CPU 时序的有关知识

①振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)。

②状态周期:2个振荡周期为1个状态周期,用S表示。振荡周期又称S周期或时钟周期。

③机器周期:1个机器周期含6个状态周期,12个振荡周期。

④指令周期:完成 1条指令所占用的全部时间,它以机器周期为单位。例如:外接晶振为 12MHz 时,51 单片机相关周期的具体值为:振荡周期=1/12us;状态周期=1/6us;机器周期=1us;指令周期=1~4us;

(2)学习定时器前需要明白的几点

①51单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器。

②定时器/计数器和单片机的CPU是相互独立的。定时器/计数器工作的过程是自动完成的,不需要 CPU 的参与。

③51单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信号对寄存器中的数据加 1。

有了定时器/计数器之后,可以增加单片机的效率,一些简单的重复加1的工作可以交给定时器/计数器处理。CPU转而处理一些复杂的事情。同时可以实现精确定时作用。

(2)计数器的配置
关于定时器1模式0(16位自动重装载模式)
截图202406201847288619.jpg

关于定时器设置外部计数的方法(主要是利用扩展T1位外部下降沿中断)
截图202406201848254066.jpg

利用STC-ISP的I/O配置工具进行测试,然后验证计数器的功能和配置;
(3)计数器的应用
截图202406201850103057.jpg

截图202406201850261918.jpg

定时器/计数器0有4种工作模式:模式0(13位定时器/计数器),模式1(16位定时器/计数器模式),模式2(8位自动重装模式),模式3(两个8位定时器/计数器)。定时器/计数器1除模式3外,其他工作模式与定时器/计数器0相同,T1在模式3时无效,停止计数。学习了相关寄存器之后,对于定时器计数器的掌握就得心应手了。
截图202406251821338579.jpg

总结:熟悉了关于计数器的使用方法和应用场景,如何利用计数器进行操作。以及寄存器的配置和定义。
以下位是与定时/计数器有关,TCON定时/计数器控制寄存器高四位含义:
  1. TF1(Timer1 Overflow Flag):定时器/计数器T1溢出标志。
  2. T1被允许计数以后,从初值开始加1计数。当最高位产生溢出时由硬件置“1”TF1,向CPU请求中断,一直保持到CPU响应中断时,才由硬件清“0”TF1 (TF1也可由程序查询清“0”)。
  3. TR1(Timer1 Run Control):定时器T1的运行控制位。
  4. 该位由软件置位和清零。当GATE (TMOD.7) =0,TR1=1时就允许T1开始计数,TR1=0时禁止T1计数。当GATE(TMOD.7) =1,TR1=1且INT1输入高电平时,才允许T1计数。
  5. TF0(Timer0 Overflow Flag):定时器/计数器T0溢出中断标志。
  6. T0被允许计数以后,从初值开始加1计数,当最高位产生溢出时,由硬件置“1”TF0,向CPU请求中断,一直保持CPU响应该中断时,才由硬件清“0”TF0( TF0也可由程序查询清“0”)。
  7. TR0(Timer0 Run Control):定时器T0的运行控制位。
  8. 该位由软件置位和清零。当GATE (TMOD.3) =0,TR0=1时就允许T0开始计数,TR0=0时禁止T0计数。当GATE(TMOD.3) =1,TR0=0且INT0输入高电平时,才允许T0计数。
复制代码
以下四位是与外部中断有关,TCON定时/计数器控制寄存器低四位含义:
  1. IE1(External Interrupt1 Enable):外部中断1请求源(INT1/P3.3) 标志。
  2. IE1=1,外部中断向CPU请求中断,当CPU响应该中断时由硬件清“0”IE1。
  3. IT1(Interrupt1 Type Control):外部中断1触发方式控制位。
  4. IT1=0时,外部中断1为低电平触发方式,当INT1 (P3.3)输入低电平时,置位IE1 。采用低电平触发方式时,外部中断源(输入到INT1) 必须保持低电平有效,直到该中断被CPI 响应,同时在该中断服务程序执行完之前,外部中断源必须被清除(P3.3要变高),否则将产生另一次中断。当IT1=1时,则外部中断1(INT1)端口由“1”一>“0”下降沿跳变,激活中断请求标志位IE1 ,向主机请求中断处理。
  5. IE0(External Interrupt0 Enable):外部中断0请求源 (INTO/P3.2) 标志。
  6. IE0=1外部中断0向CPU请求中断,当CPU响应外部中断时,由硬件清“0”IE0(边沿触发方式)。
  7. IT0(Interrupt0 Type Control):外部中断0触发方式控制位。
  8. IT0=0时,外部中断0为低电平触发方式,当INT0 (P3.2)输入低电平时,置位IE0。采用低电平触发方式时,外部中断源(输入到INTO) 必须保持低电平有效,直到该中断被CPU响应,同时在该中断服冬程序执行完之前,外部中断源必须被清除(P3.2要变高) ,否则将产生另一次中断。当IT0=1时,则外部中断0(INT0)端口由“1”一>“0”下降沿跳变,激活中断请求标志位IE0,向主机请求中断处理。
复制代码



回复 支持 反对

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-21 14:47:45 | 显示全部楼层
本帖最后由 zhangshiwei 于 2024-6-25 18:28 编辑

2024.06.21

第十三集
学习心得:简易多任务处理练习
(1)关于前面学习到的单片机各种外设资源,以及基本的编译环境搭建和LED、数码管驱动显示,定时器和计数器的使用等等,基本上对单片机的外围资源进行了熟悉,同时掌握了相关寄存器的操作;
截图202406211438202088.jpg
时钟源选择

首先让我们先对时钟进行分析,我使用的开发板没板载外部晶振,因此默认使用内部高速IRC最为时钟源,对于外设定时器的时钟源路线为如图,这里我们将IRC设置为为35MHz来作为我们的定时器时钟源,我们在ISP烧录软件可以自行修改

截图202406251825415072.jpg

在这个地方对IRC频率进行修改

截图202406251825563768.jpg


关于模块化的编程,处理了相关的任务,了解基本的编译方法和程序设计方法;
截图202406211439293625.jpg

熟悉了关于keil软件的安装和使用,关于按键这部分内容学习到了需要消除抖动的方法;
截图202406211440592777.jpg
截图202406211442201886.jpg
截图202406251826369603.jpg
这一集主要学习到综合前面的每一个外设资源,进行模块化的编程,对于整个系统的构建更为熟悉,同时了解到关于模块化编程的原理。
什么是中断系统
实现这种功能的部件称为中断系统,请示CPU中断的请求源称为中断源。微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题。通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断请求源,即规定每一个中断源有一个优先级别。
中断系统的优点
优点1:CPU总是先响应优先级别最高的中断请求。 当CPU正在处理一个中断源请求的时候(执行相应的中断服务程序),发生了另外一个优先级比它还高的中断源请求。如果CPU能够暂停对原来中断源的服务程序, 优点2:转而去处理优先级更高的中断请求源,处理完以后,再回到原低级中断服务程序,这样的过程称为中断嵌套。 这样的中断系统称为多级中断系统,没有中断嵌套功能的中断系统称为单级中断系统。 用户可以用关总中断允许位(EA/IE.7)或相应中断的允许位屏蔽相应的中断请求,也可以用打开相应的中断允许位来使CPU响应相应的中断申请, 优点3:每一个中断源可以用软件独立地控制为开中断或关中断状态, 优点4:部分中断的优先级别均可用软件设置。 高优先级的中断请求可以打断低优先级的中断,反之,低优先级的中断请求不可以打断高优先级的中断。当两个相同优先级的中断同时产生时,将由查询次序来决定系统先响应哪个中断。 不是所有的中断的优先级都可以设置,只有部分可设置。
截图202406251827499888.jpg
截图202406251828014258.jpg
截图202406251828131568.jpg
什么是外部中断
外部中断就是在单片机的一个引脚上,由于外部因素导致了一个电平的变化(比如由高变低),而通过捕获这个变化,单片机内部自主运行的程序就会被暂时打断,转而去执行相应的中断处理程序,执行完后又回到原来中断的地方继续执行原来的程序。 总的来说就是引脚上的电平变化,然后他就会进入中断。然后中断完子以后再去执行原来的程序。 什么引脚能作为外部中断口?
中断是只能在这些有标注的这个脚上才能使用。 翻看STC32G用户手册,查看INT的详细说明。引脚带INTx标识的是外部中断。
对于寄存器的操作也是有了很大的提升,关于中断这部分的知识也相比最开始学习有了很大的改善。




回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:239
  • 最近打卡:2025-03-14 14:56:59

2

主题

69

回帖

412

积分

中级会员

积分
412
发表于 2024-6-21 16:46:03 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:108
  • 最近打卡:2025-05-08 09:46:41

2

主题

48

回帖

398

积分

中级会员

积分
398
发表于 2024-6-21 18:02:15 | 显示全部楼层
本帖最后由 zhangshiwei 于 2024-6-25 18:48 编辑

2024.06.21
第十四集
关于矩阵按键的学习和操作
(1)矩阵按键的定义
通常为了减少单片机I/O口的占用,将按键排列成矩阵的形式作为按键阵列,我们就会称之为矩阵按键。
截图202406211452524906.jpg


矩阵按键工作原理
逐行扫描:通过高四位轮流输出低电平来对矩阵键盘进行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过判断低四位数据中哪一位为零来判断哪一个按键被按下。
逐列扫描:通过低四位轮流输出低电平来对矩阵键盘进行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过判断高四位数据中哪一位为零来判断哪一个按键被按下。
行列扫描:高四位全部输出低电平,低四位输出高电平。当接收到数据,低四位不全部为高电平时,说明有按键按下,然后通过接收的数据值,判断哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是哪一行有按键按下,这样就能确定是哪一个按键被按下。


矩阵按键原理图

截图202406251830415016.jpg


(2)矩阵按键的控制原理
截图202406211739307318.jpg
按键识别原理:端口默认为高电平,实时读取到引脚为低电平是表示按下。再次读取到高电平,表示松开。
第一步:现将P0.0-P0.3输出低电平,P0.6-P0.7输出高电平,如果有按键按下,按下的那一列的IO就会变成低电平,就可以判断出哪一列按下了。
第二步:现将P0.0-P0.3输出高电平,P0.6-P0.7输出低电平,如果有按键按下,按下的那一行的IO就会变成低电平,就可以判断出哪一行按下了。
第三步:行列组合一下就可以判断出是哪个按键按下了。
按键按下后导线导通,哪条线上有高电平,就会被拉低为低电平,从而检测出是哪条线路,二次检查,交叉节点就是有按键按下的按键位置。
矩阵按键程序的编写
先完成矩阵按键的功能编写。 复制9.TIM多任务为10.矩阵按键,用到P0端口,还是在之前的KEY模块基础上进行修改: 在key.h中定义:#define MateixKEY P0 //矩阵按键的引脚 定义函数MateixKEY_Read: u8 MateixKEY_Read(void); //矩阵按键读取当前是哪一个按钮按下,返回值是按键序号 在key.c中实现函数MateixKEY_Read: 先增加函数头,并把实现思路复制过来作为编写依据,围绕这三步,编写矩阵按键的读取程序: MateixKEY = 0XC0; //1100 0000 P0.6-P0.7输出高电平。


按键识别的原理:端口默认是为高电平,实时读取到引脚为低电平就是表示按键已经按下了;
截图202406211743238551.jpg

在程序中设计关于按键扫描和控制的程序,可以通过GPIO的方式进行设置和操作。
(3)矩阵按键的程序编写
矩阵按键的程序编写,密码锁就是很好的例子,可以让我们通过设置密码锁的不同输出,了解更多的实现方式。
截图202406211758492730.jpg

程序设计如下:
截图202406211759151659.jpg

总结:了解了关于矩阵按键这部分的工作原理和代码编写的过程,可以通过对于矩阵键盘的程序设计和最终的效果看到单片机的功能,理解矩阵键盘实现的思路。
截图202406211801242510.jpg

例如上述的程序思路,就是关于这部分的思路转换。



回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-9 03:35 , Processed in 0.217942 second(s), 102 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表