kmile 发表于 2023-9-30 17:52:42

打卡学习《STC32位8051单片机原理及C语言程序设计视频教程》



今天开始学习STC32G单片机,第一集通过冲哥的讲解了解到了单片机作为集成性芯片的概念。同时通过冲哥使用淘宝商品实物与应用功能的综合讲述,明白了单片机在医学、工业等方面的实际强大作用。
在问题讲解时,明白了51单片机的强大性,也感知到单片机的强应用性。
刚开始起步学习,第一集像绪论一样为自己对单片机的学习提供了明确的方向。加油!!

kmile 发表于 2023-9-30 18:46:09

第二集了解了9-4实验箱上各元器件的应用与原理。

(1)以红外遥控器做引导,了解其典型器件--红外发射与对应的红外接收
(2)电压比较的应用需要与其基准电压做比较,从而根据数据进行实时操作。这里和后面讲ADC采集的应用原理相似,即根据基准电压的对应数据,按照规则,反推出采集电压实际代表数据
(3)LED的应用最为广泛的就是流水灯
(4)数码管的原理:它的每一条灯线都可以根据信号独立点亮从而实现一组数据的显示;类似于电磁炉的显示和热水壶的数值显示

(5)万能板的存在更多是为了方便用户进行后期扩展,提供区域进行附加元器件的焊接
(6)NTC测温广泛应用于上方的电子体温计探头

(7)18B20作为温度传感,其精度高但间隔时间长,反馈数据不连续
(8)与之相比的ADC,作为模拟电压转数据的模块,它可实现连续实时测温,产生连续线性数据,同时通过基准电压得出温度数据
(9)DAC介绍不多,但可根据ADC反推,同时它可以产生波形图进而以此为基础进行功能调控
(10)数据存储方面
a.24C02作为外部存储芯片可以存储上次开机是使用数据,便于在单片机损坏时进行数据转移
b.FLASH扩展,存储空间大,可以存放图片与文字等大文件数据,实现实时存储
c.RAM可存储运行时产生的数据,但断电即丢失,需要存入上述的24C02或者FLASH内
(11)关于按键
a.独立按键,一个按键连接一个引脚,曾应用在影视剧内的典型炸弹与数码管配合使用
b.矩阵按键就是解决独立按键占用大量引脚问题,它也广泛应用于密码锁中
(12)232接口电路需要特定线进行连接,曾应用于打印机,也可进行代码烧录

以上为第二集的知识梳理,在冲哥的讲解下对实验箱内各元器件得到了初步理解,对于冲哥留的思考作业,我可能会偏向于做一个红外装置配合的密码锁,嘿嘿

kmile 发表于 2023-10-1 17:40:20

第三集,学习开发环境的搭建和程序的下载
(1)下载STC-ISP,此软件负责STC系列单片机的程序下载烧录,是单片机开发中必不可少的配置软件

(2)STC32G单片机操作手册下载,可以从STC-ISP软件内下载也可以通过官网下载。

(3)根据开发手册可知,本课程所需keil版本为C251

通过开发文档跳转到对应官网内

根据开发文档内的步骤指导,完成编译环境的下载

(4)通过软件STC-ISP下载STC32G的官方程序

在keil仿真处配置STC MCU

(5)安装配置USB驱动程序

通过上述配置后,可通过打开对应文档的项目工程文件打开keil,编译无误后生成.hex文件。STC-ISP配置好芯片型号,再打开程序文件获取对应.hex文件,即可通过此软件将程序烧录到单片机内

需要注意其他参数数据如运行频率,要与keil代码内配置一致。

kmile 发表于 2023-10-1 20:13:02

第四集的学习,开始建立第一个工程并在后期实现不断电下载
(1)首先,从原理来讲,LED点亮就是由元器件两端高低电平控制的。
过程中了解到GPIO的分组与输出电压的设置
(2)创建工程步骤
a.Project创建工程,并配置对应芯片

b.创建文本文件,并命名为.c文件。之后右键添加到工程中

c.编写程序,参照开发手册考虑控制LED灯点亮的引脚,可以使用sbit单独控制输出电平
d.进行编译,生成.hex(需要提前设置项目输出)

e.打开STC-ISP,配置对应参数,然后打开程序文件.hex,连接开发板进行下载

以上为创建工程的基础操作
同时,考虑到注册下载程序需要频繁断电。尝试使用USB_CDC不断电下载和USB_HID不断电下载,


工程开发没有问题,可实现全部点亮LED灯,但是在不断电下载处出现一定问题


想咨询一下是什么问题

kmile 发表于 2023-10-21 17:16:33

继续学习,打卡第五集
本节课的学习主要围绕C语言的数据表示与数据运算
1、首先学习了在keil上使用printf的方法
首先需要在主函数内加入
if(DeviceState!=DEVSTATE_CONFIGUSED)------>判断USB是否连接
continue;
if(bUsbOutReady){---------->判断是否接收到数据
usb_OUT_done();//接收应答
printf("");//接收数据后作出打印反映,打印双引号内字符串
}
做好基础配置后,可将编译生成的.hex文件放入STC-ISP内,运行后,模拟发送数据,系统将打印由十六进制码翻译出的字符串

2、printf内打印的知识点
(1)格式字符


在双引号内写入格式字符,打印时将识别双引号后跟随的数据根据格式进行打印
此时,%d十进制,%o八进制,%x十六进制以及%u十进制无符号是最经常使用的
%c与%s用于打印字符,根据ascii码进行数据翻译
(关于二进制有符号,二进制首位为0则为正数,正常运算;首位为1,为负数,运算时转十进制时,需求其补码,除符号位外按位取反,末位加1)
(2)转义字符

转义字符在打印时也经常使用,其中\n与\r常搭配使用用于换行
(3)ASCII码
生成的.hex为十六进制文件,打印输出时是以两位为一个字符,将十六进制根据ASCII码进行翻译得出的
3、数据运算
(1)进制转换
二进制(b),八进制(0),十进制,十六进制(0x)
二进制,仅由01,满二进一
八进制,以0开头,0,1,2,3,4,5,6,7为表示数,与二进制转换可以三位二进制转一位八进制
十六进制,以0x开头,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F为表示数,与二进制转换可以四位二进制转一位十六进制
(2)运算
按补码运算,数据的加减乘除,取余都正常
&为与运算,二进制补码11为1,10为0,01为0,00为0
|为或运算,二进制补码00为0,10为1,01为1,11为1
^为异或运算,相同为0,不同为1
~为取反运算,各位01互换取反
(3)基本类型

根据表中可得知,各数据的表示域根据其有无符号和位数bit决定

本节课为基础的理论知识,为进一步学习奠基基础,期待接下来的学习

kmile 发表于 2023-10-21 18:42:00

第六集学习打卡
1、本节课首先学习了使用Delay实现LED闪烁
功能实现核心代码
(1)基础配置
#define MAIN_Fosc      24000000UL------>此处设置TRC系统时钟频率
voiddelay_ms(u16 ms)------->ms代表毫秒数,1s=1000ms;
{
   u16 i;--------->u16      typedef unsigned int u16;即代表无符号整型
   do{
          i = MAIN_Fosc / 6000;
          while(--i);
   }while(--ms);
}
(2)功能实现
p40=0;------>三极管引脚输出低电平
while(1){
p60=0;------>引脚输出低电平,LED灯点亮
delay_ms(500);---->延时0.5s
p60=1;------>输出高电平,LED熄灭}
实现LED等每0.5秒点亮,0.5秒熄灭的功能
2、代码语法分析
(1)while与dowhile

二者区别在于while需要先判断再执行,do...while,是先执行一次再判断
(2)a--与--a自增自减
a--相当于a=a-1
符号在前先执行增减再运算
符号在后先执行运算再增减
(3)#define与typedef
二者都是用于简化符号,define新名称在前,typedef新名称在后
2、使用#define也可完成模块化编程
新建xxx.c和xxx.h文件,代表一个功能块。

xxx.h格式:
#ifndef __XXX_H
#define __XXX_H
调用头文件
函数声明...
#endif

xxx.c格式
#include “xxx.h”
函数定义
(这可避免出现头文件被重复声明,若存在该头文件将不再声明;同时,如果头文件与执行代码不处于同一文件夹,需要在keil内引用路径)

在include path处添加头文件路径
3、函数声明
函数的使用在整个功能实现上起到模块封装的作用
在模块化编程里,函数使用分为如下三步:
1.函数定义
返回值 函数名称( 入口参数 )
{
函数要执行的功能
}
@返回值:没有返回值就是void
@函数名称:避开关键词,不重复,非特殊字符随便取
@入口参数:类型+名称,多个参数“,”分开,空就写void
2.函数声明
返回值 函数名称( 入口参数 );
3.函数调用
函数名称( 入口参数 );
4、作业SOS灯光编写
(2)功能实现
p40=0;------>三极管引脚输出低电平
void short(){
p60=0;------>引脚输出低电平,LED灯点亮
delay_ms(100);---->延时0.5s
p60=1;------>输出高电平,LED熄灭
delay_ms(100);---->延时0.5s
}
void long(){
p60=0;------>引脚输出低电平,LED灯点亮
delay_ms(500);---->延时0.5s
p60=1;------>输出高电平,LED熄灭
delay_ms(500);---->延时0.5s
}
while(1){
short();
short();
short();
long();
long();
long();
short();
short();
short();
delay_ms(200);
}

kmile 发表于 2023-10-25 21:13:38

第七集学习打卡
本次学习的中心围绕按键
1、按键的原理
(1)按键通常为两个引脚

按照如图按键结构,通过检测p3.2的电平来判断按键状态。
按键SW17松开,电路处于断开,VCC电压全部分到P3.2,检测高电平,断开
按键SW17按下,电路连通,VCC电压分流,检测低电平,导通
所以,获取按键状态,只需要获得对应引脚的电平,如P32为引脚p3.2对应的按键,0为低电平表示按下,1为高电平表示松开
#define KEY P32
(2)机械开关

根据机械开关抖动的特性,获取机械开关状态时,需要进行消抖
if (KEY==0){
Delay_ms(10);---->消抖核心,观察10ms后是否仍是按下状态
if(KEY==0){
执行功能
}
}
2、按键功能应用
(1)按键按下LED点亮,松开熄灭
if(KEY==0){
Delay_ms(10);
if(KEY==0){
P67=0;//灯组第七个点亮
}else{
P67=1;//灯组第七个熄灭
}
}
(2)按键按下LED熄灭,松开点亮
if(KEY==0){
Delay_ms(10);
if(KEY==0){
P67=1;//灯组第七个熄灭
}else{
P67=0;//灯组第七个点亮
}
}
(3)按下按键一次,LED状态改变一次
if(KEY==0){
Delay_ms(10);
if(KEY==0){
while(KEY==0);//防止状态频繁切换,按下一次只做一次操作
p67=!p67;//电平翻转,状态也翻转
}
(4)按键按下一次,LED向左走一次
int LED_Data=0xFE;//1111 1110
if(KEY==0){
delay_ms(10);
if(KEY==0){
LED_Data=((LED_Data<<1)+1);//使置零位向左移一位,并用1补位
if(LED_Data==0xFF)//1111 1111代表灯光已经移到最左,需要移到最右
LED_Data=0xFE;
P6=LED_Data//P6代表整个灯组的信号状态,0位点亮,1位熄灭
while(KEY==0);
}
3、针对上面的向左移动灯光的情况,也可以使用数组,将灯光的可能状态对应二进制按顺序存入数组,使用时根据下标调用
即int *LED[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};
。。。
num=0;
f(KEY==0){
delay_ms(10);
if(KEY==0){
num++;
if(num==7)//1111 1111代表灯光已经移到最左,需要移到最右
num=0;
P6=LED//P6代表整个灯组的信号状态,0位点亮,1位熄灭
while(KEY==0);
}
}
以上为本次学习的知识梳理

kmile 发表于 2023-10-26 21:27:48

第八集蜂鸣器学习打卡
1、本次课程了解到蜂鸣器本质分为两类
(1)有源蜂鸣器:由于内置震荡源,给点后即可发声,同样造价也相对贵一些
(2)无源蜂鸣器:直流电无法发声,需要交流电(频繁切换高低电平)才能发声,但同时也可以发出多种频率的声音
从外观观察,无源蜂鸣器的背面引脚处为裸露的电路板
2、控制原理

蜂鸣器起到控制作用的依然是具有单向导通的二极管。
SYS-VCC处提供电压,若为高电平,二极管处无法导通,蜂鸣器关闭,同样P5.4处也出现高电平
若为低电平,二极管处可导通,蜂鸣器可运行,同样P5.4处为低电平
通过检测P5.4的电平可得出蜂鸣器状态
3、应用
仿造电磁炉进行操作

为简化主函数代码,模块化实现函数
定义头文件test.h,将功能函数进行声明,定义各引脚

创建test.c进行功能实现
(1)KEY控制开关机,如果没有开机其他按键功能无法实现,按键同时伴有蜂鸣器提示音

设置标识位Run_Flag为0表示未开机,为1表示开机
同时,将while(KEY1==0)判定放置功能执行后面,实现按键后实现功能且一次按键只执行一次功能
(2)KEY2按下后进行功能切换,即LED灯每按一次向左移一位,同时伴有切换提示音

本模块功能和上一节切换本质需求相同,但使用了一种新的解决办法
与每次功能切换对应的Run_Mode值相对应,每按一次便向左移动一位,
考虑到LED与位的联系将默认值次数-1,初始值为0000 0001,LED点亮要求0位点亮,所以取反得到所求
(3)注意,由于test.h文件为后添加的头文件,需要进行配置,将其所在文件夹作为头文件存储位置

4、作业
增加按键3,使选中功能运行时指示灯闪烁,不运行时常亮

考虑其中逻辑关系,必须按键2选择了功能,即Run_Mode值不为0才能执行功能;同样按键3执行时按键2也不能再切换功能;使用标志位进行实现
同时,关机时,要把各状态位清零复位
基于原蜂鸣器应用代码,按键3的执行必须是在按键2执行完后,所以要在按键2功能代码外。

以上为本次蜂鸣器学习的知识梳理,期待继续收获新知识

kmile 发表于 2023-10-30 21:15:54

第九集数码管学习打卡
1、数码管的设备原理
数码管本质就是由多个LED二极管按不同位置摆放封装组成的

如右侧示意图,代表数码管内二极管的摆放,共阴极和共阳极会影响指令信号的设置

根据内部连线图可知,本设备为共阴极,通过数码管的二极管封装位置与共阴极性质可得出码表,推算出各数字显示所需信号量

2、显示控制

若仅点亮末尾的8,只需要P6和COM0(P7.0)进行配置
(1)用数组表示1-9的内码
根据码表可得,
u8 SEG_Tab={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}
(2)尝试使用延时实现0-9的循环显示
num=0;
while(1){
P70=0//开启COM0
P6=SEG_Tab;
num++;
if(num>9)
num=0;
delay_ms(1000)
}
(3)用按键控制数字的加或减

3、拓展
通过一个按键设置数码管显示数字0-9循环,在按一下另一个按键的时候,数码管上显示的数字几,蜂鸣器就响几声。
首先设置蜂鸣器引脚
#define BEEP p54
...
int i;
while(){
....
for(i=0;i<num;i++){
BEEP=0;
delay_ms(10);
BEEP=1;
}}

kmile 发表于 2023-10-31 23:38:40

第十集数码管的动态显示知识梳理
本集的知识是基于前一集的静态显示实现的。
静态显示以末尾的单个数码管为例,展示了如何利用数组点亮LED二极管,来顺次显示0-9数字。此处的数组表示的是显示0-90数字的段码
1、动态显示的原理

本开发板共八个数码管,每个结构都如上所示,此结构为共阳极,需要先为公共端设置低电平表示输出,再为需要点亮的LED二极管对应线路设置低电平进行点亮

数码管每次点亮需要设置端口,即控制哪个数码管的公共端设为低电平,一次只能设置一个。
同时,控制数码管内LED的引脚为P6,控制各数码管电平的引脚为P7
(1)所以,设置一个数码管点亮需要先设置P7对应端口信号确认使用的数码管,再设置P6端口信号确认显示的图像
P7=0xfe;P6=0xc0;则末尾数码管显示0
(2)动态显示,则是切换P7对应端口位置信号,切换P6显示信号电平

整理出各端口位置信号,即位码的具体数据,也可存入数组中使用
为避免系统出错,在切换过程中加入延时操作,依次为P7和P6配置不同位码与段码,并进行延时切换,便可实现动态显示
(3)延时操作
由于人眼视觉很难识别50hz以上的动态显示,只要我们将延时设置为每个切换1ms,一次总循环不超过20ms,人眼就会将顺次动态显示的数码管识别为同时显示的数据
2、练习:制作简易10s免单计数器(含两位小数显示)

(1)分析
本项目本质为秒表,默认设置每次显示切换为1ms,则每10ms数据+1

秒表需要小数点,由于各数码管小数点对应位置dp,位于二进制进制的第八位,则每个数字-0x80便得到对应数字带小数点的显示信号,将数据顺次存入数组。纯数字检索对应下标恰好+10即可得到带小数点数字
为方便显示,设置数组将每位数码管需要显示的信号对应下标存入,两位小数对应小数点属于第六个数码管即显示数组下标【5】,将其存入的数据+10得到带小数点形式
设置按键控制计数器的启动与暂停,对按键进行消抖与单次按键识别,设置状态量用于记录设备的启动与停止,每按下一次状态改变一次。同时,避免数据紊乱,按下停止后再启动,原始数据会直接清空,故初始化显示数组此时应该均为0
(2)实现(核心代码)
#define KEY1 P32                //定义一个按键 引脚选择P32
#define KEY2 P33                //定义一个按键 引脚选择P33

#define BEEP P54                //定义一个按键 引脚选择P54

#define SEG_Delay1        //延时多少ms

#define MAIN_Fosc 24000000UL        //定义主时钟

char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
       
u8 SEG_Tab = { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90, 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};        //0-9段码,0-9带小数点
u8 COM_Tab = { 0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe };        //0-7的位码数组
u8 Show_Tab = {3,0,0,0,0,10,0,0};

u32 TimCount = 0;                //计数单位1ms
bit RUN_State = 0;                //开始运行/结束运行
u8 num = 0;

void sys_init();        //函数声明
void delay_ms(u16 ms);        //unsigned int

void SEG_Fre( void ) -----》定义函数,用于刷新显示,在人眼无法识别的时间内,将变化的数据显示到数码管
{
        //位码选择第一位,段码选择0
        P7 = COM_Tab;                        //位码的选择
        P6 = SEG_Tab];//需要显示的数字的内码 赋给 P6   NUM =0 -> Show_Tab] = 1 -> p6 = oxF9
        delay_ms(SEG_Delay);

        num++;
        if( num >7 )----》数码管只有8个
                num = 0;       
}

void main()                                        //程序开始运行的入口
{
       
        sys_init();                                //USB功能+IO口初始化
        usb_init();                                //usb库初始化
        EA = 1;                                        //CPU开放中断,打开总中断。
       
        while(1)                //死循环
        {
                if( DeviceState != DEVSTATE_CONFIGURED )         //
                        continue;
                if( bUsbOutReady )                                                               
                {
                        usb_OUT_done();

                }


                Show_Tab= 1;                //末尾初始显示 1
                Show_Tab= 10;                //倒数第二位显示 0.(带小数点)
                Show_Tab= 0;                //选择 0
                Show_Tab= 0;                //选择 0        ------》用于显示10.00定时数据

               
               

                if( RUN_State==1 )----》状态为运行时数据才能累加
                {
                        TimCount++;
                        Show_Tab = TimCount/10000%10;   -------》显示十位
                        Show_Tab = TimCount/1000%10+10;        -----》显示数据,同时显示小数点
                        Show_Tab = TimCount/100%10;                //显示秒表小数点后一位
                  Show_Tab = TimCount/10%10;                //取10位 ,timecount每+1位1ms,10次为10ms,显示秒表最低位
                }
               
                SEG_Fre();---》将计算结果显示

                if( KEY1 ==0 )
                {
                        delay_ms(10);
                        if( KEY1 ==0 )---》按键消抖
                        {
                                BEEP = 0;---》蜂鸣器提示
                                delay_ms(10);
                                BEEP = 1;
                                while( KEY1 ==0 )
                                {
                                        SEG_Fre();
                                }
                                if( RUN_State==0 )
                                        TimCount = 0;----》清零
                               
                                RUN_State = !RUN_State;
                        }
                }               
               
3、拓展

(1)-的显示,其实就是只点亮g,即1011 1111=0xbf,在段码数组内再填入此数据,并初始化第三个和第六个数码管为此段码一直显示如此
(2)计算数据时,num运行1000次秒区域+1,num/1000%60;num运行60000次分区域+1,num/60000%60;num运行3600000次,时区域数据+1,num/3600000%24
(3)进行if判断,当s=30,m=0,h=0时,蜂鸣器P54端口低电平启动,延时3s再设为高电平关闭
页: [1] 2
查看完整版本: 打卡学习《STC32位8051单片机原理及C语言程序设计视频教程》