webfly 发表于 2024-9-2 23:32:11

跟冲哥学习32G12K128打卡

2024.9.2 第一集:认识单片机


1、什么是单片机?
单片机是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器R@M、多种/0口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、AD转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。




2、单片机能做什么?

单片机基本就是一个小的功能减少的计算机,能写入用户程序;能读取在输入引脚上的电压信号,能在引脚上输出特定的电平信号,能在特定引脚上输出电压信号,能计算时间,能计数,能做数学运算,能做逻辑运算,能顺序动作,能通信等功能,最概括的来说就是他能做有规律可循的控制应用。


用途:单片机广泛应用于仪器仪表、家用电器、医用设备、航空航天、专用设备的智能化管理及过程控制等领域,大致可分如下几个范畴:
●智能仪器:电压、电流、功率、频率、湿度、温度、流量等的仪器仪表工业控制:工厂流水线的智能化,电梯智能化控制、各种报警系统等家用电器:电饭煲、洗衣机、电冰箱、空调机、彩电等
●网络和通信:手机,电话机、楼宇自动通信呼叫系统、列车无线通信等医用设备领域:医用呼吸机,!监护仪,超声诊断设备及病床呼叫系统等
●模块化系统:电子音乐贺卡,PLC工控板等。汽车电子:发动机控制器,基于CAN总线的汽车发动机智能电子控制器GRS导航系统、abs防抱死系统、制动系统、胎压检测等


3、介绍常见的单片机封装
单片机有很多封装形式



4、介绍32G12K128实验箱,使用实验箱或者使用stc的开发板都可正常完成学习



5、新手常见问题
(1)推荐使用51单片机入门
(2)51单片机肯定不会淘汰的,51单片机应用非常广泛,有独特的优势,长盛不衰,稳定运行,51单片机也越做越好,性能越来越强大

(3)个人入门单片机,耐心学习完一套视频,可以做做竞赛的项目,检验自己是否入门
(4)STC单片机资料做的非常好,技术支持到位;广泛赠送单片机给爱好者,非常良心
(5)做产品,选择单片机并不是越贵越好,满足需求,合适的就是最好的
(6)没学过单片机的人,已经上班了,也可以学习单片机开发
6、官网功能介绍

我一定要坚持跟着学习,静下心沉住气!

webfly 发表于 2024-9-2 23:36:00

第二集:了解硬件



介绍32G12K128实验箱具备的功能:红外发射与接收、电压比较、8位数码管、LED灯、NTC测温、18B20测温、ADC按键、PWM模拟DAC、24C02存储、独立按键、LCD接口、USB接口、232接口、FLASH扩展、RS232电路、蜂鸣器电路、测试接口、模拟示波器接口等。



实验箱的功能基本涵盖了单片机常见的功能,非常强大!

webfly 发表于 2024-9-2 23:50:50

第三集:开发环境搭建和程序下载

主要包含以下内容:



1.STC-ISP软件的下载
STC-ISP软件是开发STC家的单片机的必备神器,他不仅能下载STC全系列单片机的程序,甚至集成了虚拟显示功能,范例程序程序,在线生成工具,驱动安装等等功能。


2.STC32手册下载
可以下载阅读,也可以在线阅读,推荐下载阅读。
两种下载方式


3.PDF阅读器下载
本人已有,不需要重新下载。

4.学会PDF阅读器查阅手册
手册制作的时候已经做了详细的目录索引,可以点击目录,快速进入自己需要的内容;
可以通过书签快速定位内容;
可以通过搜索快速找到需要的内容;


5.跟着手册搭建C251开发环境
手册第五章有C251开发环境下载安装方法,跟着做就可以了。


6.程序包的下载
网站上有实验箱的代码下载,可以直接下下来参考学习


7.第一个工程的编译和下载

webfly 发表于 2024-9-2 23:53:00

下载描述

webfly 发表于 2024-9-2 23:54:28

本帖最后由 webfly 于 2024-9-3 23:25 编辑

硬件USB直接下载功能很强大


申请的开发板到了,第一时间测试了一下硬件USB,确实很好用






webfly 发表于 2024-9-2 23:55:09

本帖最后由 webfly 于 2024-9-13 23:02 编辑

第四集:建立工程点亮第一颗LED

1、LED点亮的原理
LED就是发光二极管,单片机操作指定IO口,输出高电平或者低电平,可以点亮LED;电路中,要给LED加限流电阻,防止烧坏LED



2、什么是GPIO
GPlO(general purpose intput output)是通用输入输出端口的简称,可以通过软件来读取其输入电平,或者控制他输出高低电平,点亮LED就需要用到IO口
GPIO可以按组批量操作,也可以单个操作;通过控制IO口输出高低电平,就能控制LED的亮和灭






3、建立工程,点亮led
根据官方文档,建立开发环境


环境建立好以后,新建一个工程led,然后添加一个main.c,在这个文件里编写代码

sfr P2=0xA0;
sfr P2M1=0x95;
sfr P2M0=0x96;

void main()
{
      P2M1=0x00;
      P2M0=0x00;
      while(1)
      {
                P2++;
      }
}
成功点亮P2组对应的LED

GPIO的寄存器地址从手册里找

4、思考问题

(1)思考LED为什么不会亮?注意检查程序中设置的引脚是否正确。
(2)怎么控制单独的一个引脚?sbit P00 = P0^0;//选择P0.0引脚
(3)怎么控制这个引脚输出电平?P00 = 1;//输出低电平
(4)书写规范一行一句,大括号缩进(需要设置),缩进4格,注释完整
(5)注释符号// 单行注释    /**/ 多行注释
(6)学会搜索CTRL+F

5、举一反三
使用学到的寄存器点灯方法,点亮自己做的开发板的P53端口的LED灯

sfr P5= 0xC8;
sfr P5M1 = 0xC9;   
sfr P5M0 = 0xCA;
               
void main()
{
      P5M1=0x00;
      P5M0=0x00;
      while(1)
      {
                P5++;
      }
}

6、重要知识点:实现不断电自动下载+USB CDC串口调试


本例程基于STC32G核心转接板(屠龙刀)进行编写测试。


使用USB线连接核心板USB接口与电脑;

MCU通过USB CDC(Communication Device Class)协议识别为串口设备;

使用串口助手打开CDC虚拟串口,然后向MCU发送数据,MCU返回接收到的数据到串口助手;

数据长度限制在63字节以内。

此外程序演示两种复位进入USB下载模式的方法:
1. 通过每1毫秒执行一次“KeyResetScan”函数,实现长按P3.2口按键触发MCU复位,进入USB下载模式。
   (如果不希望复位进入USB下载模式的话,可在复位代码里将 IAP_CONTR 的bit6清0,选择复位进用户程序区)
2. 通过加载“stc_usb_cdc_32g.lib”库函数,实现使用STC-ISP软件发送指令触发MCU复位,进入USB下载模式并自动下载。
   (注意:使用CDC接口触发MCU复位并自动下载功能,需要勾选端口设置:下次强制使用”STC USB Writer (HID)”进行ISP下载)

下载时, 选择时钟 24MHZ (用户可自行修改频率)。

******************************************/

#include "stc.h"
#include "usb.h"

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


char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";                      //设置自动复位到ISP区的用户接口命令

//P3.2口按键复位所需变量
bit Key_Flag;
u16 Key_cnt;

void sys_init();
void delay_ms(u8 ms);
void KeyResetScan(void);

void main()
{
    sys_init();//系统初始化
    usb_init();//USB CDC 接口配置
    EA = 1;
   
    while (1)
    {
      delay_ms(1);
      KeyResetScan();   //长按P3.2口按键触发软件复位,进入USB下载模式,不需要此功能可删除本行代码

      if(DeviceState != DEVSTATE_CONFIGURED)//等待USB完成配置
            continue;

      if (bUsbOutReady)
      {
            usb_OUT_done();    //接收应答(固定格式)
            
            printf("OutNumber=0x%X\r\n",OutNumber);//使用 printf 函数打印接收数据长度

            memcpy(UsbInBuffer, UsbOutBuffer, OutNumber);//将接收数据(UsbOutBuffer),复制到发送缓冲区(UsbInBuffer)
            usb_IN(OutNumber);      //原路返回, 用于测试
      }
    }
}

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;   //设置为准双向口

    //====== USB 初始化 ======
    P3M0 &= ~0x03;
    P3M1 |= 0x03;
   
    IRC48MCR = 0x80;
    while (!(IRC48MCR & 0x01));
   
    USBCLK = 0x00;
    USBCON = 0x90;
    //========================
}

//========================================================================
// 函数: void delay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2021-3-9
// 备注:
//========================================================================
void delay_ms(u8 ms)
{
   u16 i;
   do{
          i = MAIN_Fosc / 6000;
          while(--i);   //6T per loop
   }while(--ms);
}

//========================================================================
// 函数: void KeyResetScan(void)
// 描述: P3.2口按键长按1秒触发软件复位,进入USB下载模式。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2022-6-11
// 备注:
//========================================================================
void KeyResetScan(void)
{
    if(!P32)
    {
      if(!Key_Flag)
      {
            Key_cnt++;
            if(Key_cnt >= 1000)                //连续1000ms有效按键检测
            {
                Key_Flag = 1;                //设置按键状态,防止重复触发

                USBCON = 0x00;      //清除USB设置
                USBCLK = 0x00;
                IRC48MCR = 0x00;
               
                delay_ms(10);
                IAP_CONTR = 0x60;   //触发软件复位,从ISP开始执行
                while (1);
            }
      }
    }
    else
    {
      Key_cnt = 0;
      Key_Flag = 0;
    }
}








webfly 发表于 2024-9-2 23:55:30

本帖最后由 webfly 于 2024-9-8 14:14 编辑

第五集:C语言运算符和进制数入门

1.C语言 printf函数的实现

printf是C语言的标准输入输出库stdio提供的库函数,所以在使用它时,需要使用#include <stdio.h>指令包含stdio.h头文件。

printf的功能用以显示格式化字符串的内容,其输入参数必须包括格式化字符串,可能需要提供插入在字符串指定位置的值。格式化字符串由普通字符和转换说明组成,普通字符完全如在格式化字符串中显示的那样打印出来,而转换说明以字符%开头,表示为插入值提供的占位符。插入的值可以由常量、变量、表达式或带有返回值的函数提供,并且个数没有限制。

printf(格式化字符串, 表达式1, 表达式2, ...)

常规用法:
打印字符串 :printf(“Hello World!”)
打印格式化数据:printf(“室内温度:%.2frn”,11.2);













2.数的进制:2进制、10进制、16进制



2进制是只有两个选项的计数系统,表示为1和0。

10进制计算的唯一目的是使数值为人类可方便阅读。
(1)二进制转换十进制每个二进制位都有一个位置值。很像一系列的灯开关,位置值有0或1与它们相关联。我们所需要做的就是把“开”的位置值加起来。8位二进制,从低位到高位,第一位为2的0次方,即对应10进制的1,一次往上,最高位为2的7次方,即对应10进制的128.

(2)十六进制转换十进制十六进制数通常以0x 开头,:A=10、B=11、C=12、D=13、E=14和F=15。就像二进制系统一样。我们将只使用4位十六进制数字。从低位到高位,第一位为16的0次方,第二位为16的1次方,第三位为16的2次方,第四位为16的3次方,然后分别乘以所在位的值
3.C语言常用运算符


① 、算术运算符:加(+)、减(-)、乘(*)、除(/);
                  模(余)运算符(%):不允许出现浮点型,余数正负取决于被除数正负;
                  自增自减(++i、-i;i++、i-)

②、位运算符:
                  右移(>>) 左移(<<)
                  按位与(&)
                  按位或(|)
                  按位异或(^)
                  取反(~)

4.数据的基本类型




其中,以下四个类型是C51扩展数据类型:
数据类型      数据长度      数值范围      注释
bit      1位      0或1      位型
sbit      1位      0或1      可位寻址的位型
sfr      单字节      0~255      特殊功能寄存器
sfr16      双字节      0~65535      16位特殊功能寄存器



webfly 发表于 2024-9-3 10:29:07

本帖最后由 webfly 于 2024-9-10 22:44 编辑

第六集:LED闪烁第六集:LED闪烁和花式点灯上和花式点灯
1、基于Delay实现的LED闪烁
1秒= 1000毫秒=1000000微秒

自定义一个延时函数

void delay_ms(unsigned int ms)
{
      unsigned int i;
      do
      {
                i = MAIN_Fosc / 6000;
                while(--i);
      }while(--ms);
}


完整测试代码:

#include <STC32G.H>
#define MAIN_Fosc 24000000UL                //定义一个IRC系统时钟
void delay_ms(unsigned int ms);

sfr P2=0xA0;
sfr P2M1=0x95;
sfr P2M0=0x96;

//自定义延时函数
void delay_ms(unsigned int ms)
{
      unsigned int i;
      do
      {
                i = MAIN_Fosc / 6000;
                while(--i);
      }while(--ms);
}

void main()
{
      //寄存器点灯
      P2M1=0x00;
      P2M0=0x00;
//      while(1)
//      {
//                P2++;
//      }
      
      //自定义函数闪烁
                while(1)
      {
                P20 = 0;                        //点亮
                delay_ms(200);
                P20 = 1;                        //熄灭
                delay_ms(200);
                P20 = 0;                        //点亮
                delay_ms(200);
                P20 = 1;                        //熄灭
                delay_ms(200);
                P20 = 0;                        //点亮
                delay_ms(200);
                P20 = 1;                        //熄灭

                delay_ms(1000);
      }
      
}




关于while的用法



2、函数的用法



int Add(int a,int b)
{
    return a+b;
}


3、新建文件,使用模块化编程


       模块化编程是一种有效的编程方法,‌它通过将程序的不同部分(‌模块)‌分离成独立的文件,‌以提高代码的可读性、‌可维护性和可重用性。‌
       在不同的编程语言中,‌模块化编程的实现方式略有不同,‌但基本原理相似。‌以下是在不同编程语言中实现模块化编程的步骤:‌
       将相关的函数和变量定义在不同的.c文件中,‌每个文件实现特定的功能,‌
       为每个模块创建一个对应的头文件,‌后缀为.h,‌用于声明模块中的函数和变量,‌以便其他文件可以使用。
       在主文件(‌如main.c)‌中,‌通过#include指令包含所需的头文件,‌并调用相应模块中的函数。‌

新建xxx.c和xxx.h文件,代表一个功能块。
   xxx.h格式:
      #ifndef __XXX_H
      #define __XXX_H
      调用头文件
      函数声明...
      #endif
   xxx.c格式
      #include “xxx.h”
      函数定义

webfly 发表于 2024-9-3 10:29:20

本帖最后由 webfly 于 2024-9-13 23:53 编辑

第七集:按键点灯


1、按键
按键有常开的,有常闭的,常开的摁下以后导通,常闭的按下以后断开




按键摁下以后,需要一定的时间以后才能稳定,所以会有抖动,需要做消抖处理






    if( KEY == 0 )
    {
          Delay_ms(10);
          if( KEY == 0 )
          {
            while(KEY == 0);
            执行具体的功能
          }
    }


2、按键的应用:

    按键按下LED灯亮,松开熄灭;


                              if(P32==0)
                              {
                                        delay_ms(10);
                                        if( P32==0 ){
                                                printf("按键P32已经按下");
                                                P60 = 0;
                                        }
                                        else
                                        {
                                                printf("按键P32已经放开");
                                                P60=1;
                                        }
                              }


                              

    按键按下KED灯熄灭,松开点亮;
if( P33== 0)                              //判断按键有没有按下{      delay_ms(10);      if( P33== 0 )      {         printf("按键P33已经按下\r\n");         P67 = 1;                                 //LED熄灭      }}else    {    P67 = 0;                                       //LED熄灭    }   
    按键按下一次,LED状态改变一次;
if( P33== 0)                              //判断按键有没有按下{    delay_ms(10);    if( P33== 0 )                                {         while(KEY2 == 0)                        {
         }         printf("按键P33已经按下,led取反一次\r\n");         P67 = !P67;      //LED熄灭                                  }}
数组的使用





webfly 发表于 2024-9-3 10:29:48

本帖最后由 webfly 于 2024-9-19 09:45 编辑

第八集:蜂鸣器的应用

1、蜂鸣器分为有源蜂鸣器和无源蜂鸣器,有源是指内部有震荡源,能够驱动蜂鸣器发声,振荡源有芯片、二极管、三极管等,所以,只要一通电就会发声。声音种类有连续声、间断声、报警声等。



无源的蜂鸣器是指内部是没有震荡源,所以,通电是不会发声的,必须有信号来驱动它,才可以使其发声,声音频率可控。






如何区分是有源蜂鸣器还是无源蜂鸣器?
(1)通过外观:可以把蜂鸣器焊脚朝天,如果电路板是黑色的表明是有源的,如果电路板是绿色的表示无源的 ;
(2)测试:把万用表调到欧姆档位,如果电阻数值有显示则是无源蜂鸣器,如果发出持续的声音,则是有源蜂鸣器。


2、STC32G开发板控制有源蜂鸣器:P54引脚低电平,蜂鸣器打开;P54引脚高电平,蜂鸣器关闭。




3、STC32G开发板控制有源蜂鸣器代码


#include "COMM/stc.h"                                          //调用头文件
#include "COMM/usb.h"
#include "test.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
      
void sys_init();                                                      //函数声明
void delay_ms(u16 ms);                                           //unsigned int
void main()                                                            //程序开始运行的入口
{
      u8 LED_Data = 0XFE;
      
      u8 num=0;
      u8 LED_DataTab = { 0XFE,0XFD, 0XFB,0XF7,0XEF,0XDF,0XBF,0X7F};
      
      sys_init();                                                          //USB功能+IO口初始化
      usb_init();                                                         //usb库初始化
      EA = 1;                                                             //CPU开放中断,打开总中断。
      
      P6 = LED_Data;
      while(1)                                                            //死循环
      {
                if( DeviceState != DEVSTATE_CONFIGURED )         
                        continue;
                if( bUsbOutReady )                                                               
                {
                        usb_OUT_done();
                }
                if( KEY1 == 0)
                {
                        delay_ms(10);
                        if(KEY1 == 0 )
                        {
                              while(KEY1 == 0 );
                              BEEP = !BEEP;
                        }
                }
      }
}





4、蜂鸣器实战应用

页: [1] 2 3
查看完整版本: 跟冲哥学习32G12K128打卡