找回密码
 立即注册
楼主: ccczz***

跟着何宾老师学习单片机-STC32,【实验箱已收到】

[复制链接]
  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-5 20:33:06 | 显示全部楼层
    本帖最后由 ccczzzwwwyy 于 2023-9-5 20:34 编辑

    9月5日,何宾老师:
    类型限定符
    C251编译器支持两个类型限定符,包括const和volatile
    const类型限定符声明了一个在运行时未修改的对象
    volatile类型限定符声明了一个对象,该对象的值可能会被出现
    在其中的代码之外的某个对象修改
    在嵌入式系统中,这通常是硬件

    类型限定符
    —const
    在ANSIC中,const类型限定符用于定义和访问常数且不能更改的对象
    用const声明的变量不能在程序中赋值
    仅用const类型限定符声明的变量保存在与其定义相关联的存储器区域
    (data, idata,xdata等)中
    constunsigned short xdata a[10]={0,1,2,3,4,5,6,7,8,9};
    需要在ROM中定位的变量必须用code存储器类型声明
    constunsigned short code a[10]={0,1,2,3,4,5,6,7,8,9);

    类型限定符
    ——const
    常数对象通常在定义(在源文件中)时初始化
    下面的变量定义显示了创建常数对象的不同方法:
    const inttable[2][2]={0, 2, 4, 8); // table保存在默认的存储器类中
    const floatfar pi=3.1415926;                  // pi保存在HCONST存储器类中
    printf("This is a string\n" );                       // 字符串保存在HCONST存储器类中

    类型限定符
    --const
    当使用指向const对象的指针时,可以在指针定义中排除const类型限定符,例如:
    constunsigned char mask[]={0x01, 0x02, 0x04, Ox08);
    constunsigned char *cp=mask;
    unsigned char*p=mask;                                    //与cp效果相同
    *p=' а';                                                        // 这里没效果,不会导致警告或错误
    *ср=' а';                                                         //这会导致错误
    从上面可知,可以将常数对象mask的地址分配给非常数的指针p,然后使用该指针更改常数对象。在这种情况下,编译器会生成代码写入常数对象。该代码的效果未定义,可能或无法按预期工作
    不能使用const指针来更改它指向的常数对象。如果这样做,将导致编译器错误

    类型限定符
    —const
    const的一个有趣的用法是定义一个不可更改的指针
    例如:
    chartext[]=" This is a string ";
    char *consttextp=text;
    *textp=' A';                                         // 这是正常的(它会改变test[0])
    textp++;                                               // 这会导致错误(textp为常数)
    textp[2]='B';                                             //这是正常的(它会改变test[2])

    类型限定符
    ——volatile
    易失性类型限定符用于限制编译器对对象值的假设
    例如:
    unsigned charreg1;                                                //硬件寄存器#1
    unsigned charreg2;                                                // 硬件寄存器#2

    void func(void)      

    {
    while (reg1& 0x01)                                          // 当设置位0时,重复

    {
    reg2 = 0x00;                                   // 轮询位7
    reg2 = 0x80;                                                           

    类型限定符
    --volatile
    因此,引入volatile类型限定符来解决以上的问题。比如:
    volatileunsigned char reg1;                         // 硬件寄存器#1
    volatileunsigned char reg2;                          // 硬件寄存器#2
    void func(void)
    {
    while (reg1& Ox01)                                            // 当设置位0时,重复
    {
    reg2 = 0x00;                                          // 轮询位7
    reg2 = 0x80;
    }
    }
    通过将reg1和reg2定义为volatile,编译器现在知道对这些变量的访问可能不会被优化。生成的代码按需要执行
    类型限定符
    -volatile
    【例8—3】不同数据类型运算的C语言描述
    void main()
    {
    volatile charedata a=100, b=-90,c;                   //edata空间放置双字变量
    volatile intedata d=10000, e=-5000,f;                //edata空间放置字符变量
    edata空间放置字变量
    volatile longint edata h=20000000, i=-10000000,j;
    volatile bitebdata x=1, y=1, z, w;                             // ebdata空间放置位变量
    c=a+b;                                                                       // 字符变量a和b相加
    f=d+e;                                                                         // 字变量d和e相加
    j=h+i;                                                                // 双字变量h和i相加
    z=x&y;                                                           // 位变量x和y逻辑“与”
    w=x^y;                                                           // 位变量x和y逻辑“异或”
    }
    类型限定符
    volatile
    【例8—4】浮点数运算的实现(一)
    void main()
    {
    volatilefloata=100.0,b=200.0;
    volatilefloat edata c=a+b;
    }
    类型限定符
    ——volatile
    【例8—6】数组元素存储和运算的C语言代码
    void main()
    {
    const charcode table[]={1,2,4,8};
    volatile chari=0,sum=0;
    for(i=0;i<4;i++)
    sum+=table;
    }
    存储类别
    C语言支持许多可以应用于程序变量的存储类
    存储类用于定义变量和函数的范围和生存周期,这些存储类关键
    字包括:
    auto
    register
    static
    extern

    存储类别
    auto
    auto存储类是本地变量默认的存储类
    其格式如下:
    autodata-type name <[>=value<]>
    其中
    data—type为变量的数据类型
    name是变量的名字
    value是分配给变量的值
    需要注意,存储类auto只能在函数定义内使用

    存储类别
    ——register
    register存储类定义了应该保存在一个或多个寄存器中而不是RAM中的局部变量
    其格式如下:
    registerdata-type name <[>=value<]>;
    其中
    data—type为变量的数据类型
    name为变量的名字
    value为分配给变量的值
    通常,C251编译器忽略register存储类。如果有可能,所有变量都保存在寄存器中
    注:存储类register只能在函数定义内使用

    存储类别
    ——static
    static存储类限制变量的范围并修改局部变量的生存期
    其格式如下:
    staticdata-type name <[>=value<]>;
    其中
    data—type为变量的数据类型
    name为变量的名字
    value是分配给变量的值
    使用static在函数外部声明变量时,无法在声明变量的源文件外部访问该变量
    当使用static在函数内部声明变量时,该变量在启动时就被初始化(与其他全局变量一样) ,并且在调用该函数时保留其值
    在进入函数时,它不会被重新初始化

    存储类别
    -extern
    extern存储类声明在另一个源模块中定义的全局变量
    其格式如下:
    externdata-name name;
    其中
    data—type为变量的数据类型
    name为变量的名字
    当使用extern声明变量时,无法初始化该变量,这是因为它已经在定义的位置初始化了

    存储类别
    【例8—7】存储类用法的C语言描述
    在extern.c文件中定义变量
    short inta=3000,b=-2000;
    在main.c文件中调用外部变量
    #include"math.h"
    extern shortint a,b;
    void main()
    {
    volatile longint c;
    c=a*b;
    }
    存储类别
    该C语言代码对应的反汇编代码
    3: voidmain()
    4: {
    5:       volatile long int c;
    6:              c=a*b;
    OxFF0042    7E17000A       MOV                WR2,b(0x000A)
    OxFF0046    1A02                  MOVS              WRO,R2
    OxFF0048     1A00              MOVS              WRO,RO
    0xFF004A     7E370008           MOV             WR6,a(0x0008)
    OxFF004E     1A26                   MOVS            WR4,R6
    OxFF0050      1A24                   MOVS           WR4,R4
    0xFF0052       12605A              LCALL           C?LMUL(C:0x005A)
    OxFF0055       7A1F000C       MOV             c(0x000C),DR4

    绝对位置变量
    变量可以使用_at_关键字定位在绝对存储器的位置
    其格式为:
    type[memory_type]variable_name_at_const_expr;
    其中
    type为变量的类型
    memory_type为变量的存储器类型。如果在声明中排除该项,则使用默认存储器类型
    variable_name为变量的名字
    const_expr为必须计算为绝对常数值的表达式。表达式的结果是定位变量的地址

    绝对位置变量
    随在_at_关键字后面的绝对地址必须符合变量存储空间的
    物理边界
    对于xdata和code存储器类型,该表达式解释为相对于存储器类
    型的基地址的偏移量
    C251编译器为xdata和code变量生成OFFS重定位类型
    对于其他存储器类型,at_表达式表示STC32G系列单片机中的
    绝对存储器位置
    C251编译器检查地址范围是否有效

    绝对位置变量
    【例8—9】_at_关键字的C语言用法
    Structum                                                 // 定义结构体num
    char a;                                                   // 定义结构体中的字符型变量a
    short int b;                                            //定义结构体中的16位整数变量b
    long int c;                                               // 定义结构体中的32位整数变量c
    };
    // 结构变量x,位于edata存储类地址0x00200
    struct numedata x_at_Ox0200;
    // 定义字符数组,位于code存储类地址0x0010
    char codestr[20] _at_Ox0010 ="hello world\n";

    绝对位置变量
    void main()                                                // 定义main主函数
    {
    x.a=0xab;                                                       // 初始化x.a
    x.b=0x1234;                                                // 初始化x.b
    x.c=0x5a5aa5a5;                                        // 初始化x.c
    }
    指针
    C251编译器支持使用*字符声明变量指针
    C251编译器可用于执行标准C中可用的所有操作

    指针
    指针声明中的存储器类型
    可以在指针声明中使用存储器类型来定义指针的大小
    没有显式存储器类型的指针称为通用指针
    具有显式存储器类型的指针称为存储器特定指针
    特定于存储器的指针为每个变量访问生成更高效的代码

    指针
    指针声明中的存储器类型
    声明指针的规则
    变量声明                       指针大小(位)                         指针声明
    char c;                             16/32                       char *ptr; (指针大小取决于使用的存储器模型)
    int near nc;                     16                             int near *np;
    float datadf;                    8                                float data *dp;或float near *dp;
    char idataindex;           16                              char idata *ip; 或 char near *ip;
    long xdata x;                   16                             long xdata *xp;
    const charcode c='A';  16                             char code *cp; /* 可以忽略const*/
    const charnear n=5;     16                              char near *np; /* 可以忽略const*/
    unsigned longfar I;        32                              long far *Ip;
    char huge hc;                   32                             char huge *hp_ptr;
    void nearfunc1(void);    16                           void (near *fp1)(void);
    int farfunc2(void);           32                             int (far *fp2)(void);

    指针
    指针声明中的存储器类型
    指向data或idata对象的指针可以使用near存储器类型声明
    因为near指针也可以访问data或idata存储器
    在TINY和XTINY存储器模型中,默认指针大小为16位,指针的
    默认存储器类型为near *
    要访问0x010000以上的存储器区域,必须在指针声明中指定存储器类型
    为far*或huge*
    使用far或者huge指针,可以寻址near,data或idata对象。
    不同之处在于
    far或huge指针访问使用@DPk指令,然而near指针使用更高效的
    @WRj指令
    far或huge对象不能用near指针寻址

    指针
    指针声明中的存储器类型
    下面给出一些使用例子:
    char near*px;
    声明一个指针,该指针引用near存储器类型中char类型的对象。指针本身保存在默认存储器类型中(取决于使用的存储器模型)。大小为两个字节
    char near*data pdx;
    该声明与先前的声明相对应,只是指针本身被明确地放置到数据存储器(data)中,而与使用中地存储器模型无关
    int (* xdata fp) (void);
    该声明定义了函数指针,该函数指针被显式放置到xdata存储器类型中,而与使用地存储器模型无关。所寻址的函数的类型为void func (void)

    指针
    指针声明中的存储器类型
    Struct  time{
    char hour;
    char min;
    char sec;
    struct timenear *pxtime;
    };
    除了其他元素之外,该结构还包含指向另一个结构的指针pxtime,该结构必须位于near存储器类型中。指针pxtime的大小为两个字节
    指针声明中的存储器类型
    struct timefar *ptime;
    该声明定义了一个指针,该指针保存在默认的存储器类型中,并引用位于far存储器类型中的struct time。指针ptime需要四个字节
    ptime->pxtime->hour=12;
    使用前面的两个声明。指针pxtime是从结构间接加载的。它指向structtime,位于near存储器类型。将值12分配给该结构的成员hour

    指针
    指针声明中的存储器类型
    struct timefar *ptime;
    该声明定义了一个指针,该指针保存在默认的存储器类型中,并引用位于far存储器类型中的struct time。指针ptime需要四个字节
    ptime->pxtime->hour=12;
    使用前面的两个声明。指针pxtime是从结构间接加载的。它指向structtime,位于near存储器类型。将值12分配给该结构的成员hour

    指针
    指针转换
    C251编译器可以转换指针的存储器类型
    指针转换可以由使用类型强制转换的显式程序代码强制执行,也可以由编译器强制执行
    通用指针与TINY或XTINY存储器模型的near*指针定义相同。对于所有
    其他存储器模型,通用指针与far *指针定义相同

    指针
    指针转换
    当存储器特定指针作为参数传递给需要通用指针的函数时,C251编译器将存储器特定指针转换为通用指针
    C251运行时库函数(如printf, sprintf和gets)的情况就是如此,这些函数使用通用指针作为参数
    指针
    指针转换
    extern intprintf (void *format, ...);
    extern intmyfunc (void near *p, int data *dq);
    int data *dp;
    const charnear *fmt = "value = %d | %04XH\n";
    voiddebug_print (void) {
    printf (fmt,*dp);                                                                   // 转换fmt
    myfunc (fmt,nx);                                                              // 没有转换

    指针
    指针转换
    在对printf的调用中,表示2字节near指针的参数fmt被自动转换成强制为通用指针
    这样做是因为printf的原型需要一个通用指针作为第一个参数。根据存储器模型,通用指针的大小为2个字节或4个字节
    注:在TINY或XTINY存储器模型中,无法使用标准C251运行时库函数访问0x010000以上的存储器位置。因此,printf的格式字符串必须声明为constchar near,如果将格式字符串声明为char code (如C51程序中所做的那样)则printf仅适用于SMALL, XSMALL或LARGE存储器模型
    由于将地址空间看作是线性实体,因此指针转换主要通过扩展或截断指针的高位部分完成
    转换指针所涉及的过程
    转换类型                                                                        功能描述
    far *到code                        far *的低位字(2个字节)用作偏移量,丢弃高阶字
    far *到data *                            far *的低位字用作偏移量
    far *到idata*
    far *到near*                             far *的低位字(2个字节)用作偏移量
    far *到xdata*                            far *的低位字(2个字节)用作偏移量
    far *到pdata*                            far *的低位字用作偏移量
    code *到far *       far*的高位字设置code的基地址(默认0xFF)。使用code *的2字节偏移量
    idata *到far*       对于idata/data, far *的高位字设置为0x00, Idata */data的1字节偏移量被
    data *到far*         转换为无符号整数,并用作低位字
    near *到far*          对于near, far*的高位字设置为0x00, near*的2字节偏移用作低位字
    xdata *到far*           far *的高位字设置为xdata的基地址(默认1) 。xdata *的2字节偏移
    用作低位字
    pdata *到far*         far *的高位字设置为xdata的基地址(默认1)。偏移的高位字节设置pdata的页。pdata*的1字节偏移用作偏移的低位字节

    near *到data*                           只有near *指针的低位字节用作偏移
    near *到idata*
    data *到near*                  idata */data *的1字节偏移转换为unsigned int,以及用作near *指针
    idata *到near *              的偏移

    注:在表中没有列出来的所有指针转换都是非法的,在编译时会产生警告信息

    指针转换
    转换指针所涉及的过程
    转换类型                                                                           功能描述
    far *到code*                                     far*的低位字(2个字节)用作偏移量,丢弃高阶字
    far *到data*                                             far *的低位字用作偏移量
    far *到idata*
    far *到near*                                      far *的低位字(2个字节)用作偏移量
    far *到xdata *                                           far *的低位字(2个字节)用作偏移量
    far *到pdata *                                              far *的低位字用作偏移量
    code *到far*                    far *的高位字设置code的基地址(默认OxFF)。使用code *的2字节偏移量

    设计实例(一)
    声明和使用指针的C语言描述
    #include"stdio.h"                                  // 包含头文件stdio.h
    #include"reg251s.h"                            // 包含头文件reg251s.h
    void main()                                           // 定义main主函数
    {
    volatile inta,b;                                         //声明整型变量a和b
    volatile intedata *p2,*p3;                   //声明指针变量*p2和*p3,在edata区域
    SCON= 0x52;                                             // 初始化串口寄存器SCON
    TMOD = 0x20;                                           // 初始化串口寄存器TMOD
    TCON = 0x69;                                       // 初始化串口寄存器TCON
    TH1 = 0xF3;                                          // 初始化串口寄存器TH1

    scanf(“%d,%d”,&a,&b);       //调用scanf函数,输入变量a和b的值
    p2=&a;                                                    //通过取地址符号'&',使得指针p2指向变量a
    printf(“(*p2)=%d\n”,*p2);        //调用printf函数,显示*p2的内容
    printf(“&p2=%p\n”,&p2):                   //调用printf函数,显示指针对象*p2的地址
    printf(“&a=%p\n”,&a);                  //调用printf函数,显示变量a的地址
    p3=&b;                                             // 通过取地址符号’&',使得指针p3指向变量b
    printf(“(*p3)=%d\n”,*p3);       // 调用printf函数,显示*p3的内容
    printf(“&p3=%p\n”,&p3);               //调用printf函数,显示指针对象*p3的地址
    printf(“&b=%p\n”,&b);                     //调用printf函数,显示变量b的地址
    while(1);                                                // 无限循环,用于设置断点的位置
    }
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-6 21:40:11 | 显示全部楼层
    9月6日,陈老师:

    随着数字电子技术及计算机技术的广泛普及与应用,数字信号的传输与处理日趋普遍。
    自然形态下的物理量多以模拟量的形式存在的,如温度、湿度、压力、流量、速度等,实际生产、生活和科学实验中还会遇到化学量、生物量(包括医学)等。
    从信号工程的角度来看,要进行信号的计算机处理,上述所有的物理量、化学量和生物量等都需要使用相应的传感器,将其转换成电信号(称之为模拟量)
    将模拟量转换为计算机能够识别处理的数字量,而后再进行信号的传输、处理、存储、显示和控制。
    同样,计算机控制外部设备时,如电动调节阀、调速系统等,需要将计算机输出的数字信号变换成外设能够接受的模拟信号。将模拟量转换成数字量的器件称为模数转换器(Analog toDigital Converter,ADC),也称为A/D转换器或者ADC器件;
    ·以单片机为核心,具有模拟量输入和输出的应用系统结构如图所示。
    1-1.JPG
    传感器和变送器的区别
    传感器是一种把非电量转变成电信号的器件。
    MEMS
    检测仪表在模拟电子技术条件下,一般包括传感器、检测点取样设备及放大器(进行抗干扰处理及信号传输),当然还有电源及现场显示部分(可选择)。电信号一般分为连续量、离散量两种,实际上还可分成模拟量、开关量、脉冲量等。
    模拟信号一般采用4—20mA DC的标准信号传输。数字化过程中,常常把传感器和微处理器及通信网络接口封装在一个器件(称为检测仪表)中,完成信息获取、处理、传输、存贮等功能。
    在自动化系统中经常把检测仪表称为变送器,如温度变送器、压力变送器等。
    一、模数转换器的工作原理
    根据转换的工作原理不同,模数转换器可以分为计数—比较式、逐次逼近式和双斜率积分式。
    计数—比较式模数转换器结构简单,价格便宜,转换速度慢,较少采用。
    下面主要介绍逐次逼近式模数转换器的工作原理。
    1、逐次逼近式模数转换器的工作原理
    逐次逼近式模数转换器电路框图如图所示。
    1-2.JPG
    工作过程
    当模数转换器收到“转换命令”并清除SAR寄存器后,控制电路先设定SAR中的最高位为“1”,其余位为“0”,此预测数据被送至D/A转换器,转换成电压Vc。
    然后将Vc与输入模拟电压Vx在高增益的比较器中进行比较,比较器的的输出为逻辑0或逻辑1。
    ·如果Vx≥Vc,说明此位置“1”是对的,应予保留(1);
    ·如果Vx<Vc,说明此位置“1”不合适,应予清除(0)。
    按该方法继续对次高位进行转换、比较和判断,决定次高位应取“1”还是取°.0,,
    ·重复上述过程,直至确定SAR最低位为止。
    该过程完成后,状态线改变状态,表示已完成一次完整的转换,SAR中的内容就是与输入的模拟电压对应的二进制数字代码。
    二、模数转换器的性能指标
    A/D转换器是实现单片机数据采集的常用外围器件。A/D转换器的品种繁多,性能各异,在设计数据采集系统时,首先碰到的问题就是如何选择合适的A/D转换器以满足系统设计的要求。
    选择A/D转换器需要综合考虑多项因素,如系统技术指标、成本、功耗、安装等。
    1、分辨率
    分辨率是A/D转换器能够分辨最小信号的能力,表示数字量变化一个相邻数码所需输入模拟电压的变化量。分辨率越高,转换时对输入模拟信号变化的反应就越灵敏。
    例如,8位A/D转换器能够分辨出满刻度的1/256,若满刻度输入电压为5V,则该8位A/D转换器能够分辨出输入电压变化的最小值约为19.5mV。
    13 分辨率常用A/D转换器输出的二进制位数表示。
    ·常见的A/0转换器有8位、10位、12位、14位和16位等。
    5、采样/保持器
    采样/保持也称为跟踪/保持(Track/Hold缩写T/H)。
    原则上采集直流和变化非常缓慢的模拟信号时可不用采样保持器。
    对于其他模拟信号一般都要加采样保持器。如果信号频率不高,A/D转换器的转换时间短,即使用高速A/D转换器时,也可不用采样/保持器。
    6、量程
    量程即所能转换的电压范围,如2.5V、5V和10V。
    7、满刻度误差
    满度输出时对应的输入信号与理想输入信号值之差称为满刻度误差。
    8、线性度
    实际转换器的转移函数与理想直线的最大偏移称为线性度。
    9、数字接口方式
    根据转换的数据输出接口方式,A/D转换器可以分为并行接口和串行接口两种方式。
    并行方式一般在转换后可直接读取数据,具有明显的转换速度优势,但芯片的引脚比较多;
    串行方式所用芯片引脚少,封装小,使用串行器件可以节省I/O资源,但需要软件处理才能得到所需要的数据。
    STC8H8K64U单片机内部集成了一个12位高速A/D转换器,使用单片机集成的ADC时,不存在接口问题。
    10、模拟信号类型
    通常ADC器件的模拟输入信号都是电压信号。同时根据信号是否过零,还分成单极性(Unipolar)信号和双极性(Bipolar)信号。
    11、电源电压
    电源电压有单电源、双电源和不同电压范围之分,如果选用单+5V电源的芯片则可以使用单片机系统电源。
    12、功耗
    一般CMOS工艺的芯片功耗较低,对于电池供电的手持系统对功耗要求比较高的场合一定要注意功耗指标。
    13、封装
    常见的封装有双列直插封装(DIP)和表贴型(SMD)封装。
    1、模数转换器的结构
    STC8H8K64U单片机ADC的结构如图所示。
    1-3.JPG
    2、与ADC有关的特殊功能寄存器
    (1)ADC控制寄存器ADC_CONTR
    符号                      地址           b7                     b6                           b5             b4                b3  b2b1  b0
    ADC_CONTR   BCH   ADC_POWER   ADC_START ADC_FLAG   ADC_EPWMT  ADC_CHS[3:0]
    ADC_POWER:ADC电源控制位
    0:关闭ADC电源
    1:打开ADC电源。
    建议进入空闲模式和掉电模式前将ADC电源关闭,以降低功耗。特别注意:
    给MCU的内部ADC模块电源打开后,需等待约1ms,等MCU内部的ADC电源稳定后再让ADC工作。
    2、与ADC有关的特殊功能寄存器
    (1)ADC控制寄存器ADC_CONTR
    符号                      地址     b7                             b6                  b5                      b4                  b3 b2  b1b0
    ADC_CONTR    BCH    ADC_POWER  ADC_START  ADC_FLAG   ADC_EPWM ADC_CHS[3:0]
    ADC_START:ADC转换启动控制位。
    写入1后开始ADC转换,转换完成后硬件自动将此位清零。
    0:无影响。即使ADC已经开始转换工作,写0也不会停止A/D转换。
    1:开始ADC转换,转换完成后硬件自动将此位清零。
    ADC_FLAG:ADC转换结束标志位。
    当ADC完成一次转换后,硬件会自动将此位置1,并向CPU提出中断请求。此标志位必须软件清零。
    2、与ADC有关的特殊功能寄存器
    (1)ADC控制寄存器ADC_CONTR
    符号                      地址    b7                                b6                     b5                 b4                    b3 b2 b1  bo
    ADC_CONTR    BCH    ADC_POWER   ADC_START   ADC_FLAG   ADC_EPWMT  ADC_CHS[3:0]
    ADC_EPWMT:使能PWM实时触发ADC功能。
    ADC_CHS[3:0]:ADC模拟通道选择位
    注意:被选择为ADC输入通道的I/O口,必须设置PxM0/PxM1寄存器将I/O口模式设置为高阻输入模式。
    另外,如果MCU进入掉电模式/时钟停振模式后,仍需要使能ADC通道,则需要设置PxIE寄存器关闭数字输入通道,以防止外部模拟输入信号忽高忽低而产生额外的功耗。
    2、与ADC有关的特殊功能寄存器
    (1)ADC控制寄存器ADC_CONTR
    符号                      地址       b7                          b6                         b5                    b4                           b3 b2  b1 bo
    ADC_CONTR     BCH   ADC_POWER   ADC_START   ADC_FLAG   ADC_EPWMT    ADC_CHS[3:0]
    ADC_CHS[3:0]:ADC模拟通道选择位
    ADC_CHS                                                 ADC通道                                                       引脚
    0000                                                              ADCO                                                         P1.0
    0001                                                               ADC1                                                          P1.1
    0010                                                               ADC2                                                            P5.4
    0011                                                               ADC3                                                            P1.3
    ………                                                     ..-                                                        ……
    0111                                                               ADC7                                                              P1.7
    1000                                                              ADC8                                                               PO.0
       …….                                                     ….                                                    …..
    1010                                                    ADC14                                                   P0.6
    1111                                                测试内部1.19V                                           有
    (2)ADC配置寄存器(ADCCFG)
    符号                 地址        b7         b6            b5          b4      b3       b2     b1          b0
    ADCCFG      DEH                               RESFMT                           SPEED[3:0] -
    RESFMT:ADC转换结果格式控制位
    0:转换结果左对齐。
    ADC_RES保存结果的高8位,ADC_RESL保存结果的低4位。格式如下:
    1-4.JPG
    1:转换结果右对齐。ADC_RES保存结果的高4位,ADC_RESL保存结果的低8位。格式如下:
    1-5.JPG
    (2)ADC配置寄存器(ADCCFG)
    符号             地址             b7       b6            b5             b4    b3   b2   b1   bo
    ADCCFG     DEH                                 RESFMT                SPEED[3:0]
    SPEED[3:0]:设置ADC工作时钟频率。
    {FADC=SYSclk/2/(SPEED+1)}
    SPEED[3:0]                                            给ADC的工作时钟频率
    0000                                                        SYSclk/2/1
    0001                                                          SYSclk/2/2
    0010                                                          SYSclk/2/3
    1101                                                           SYSclk/2/14
    1110                                                            SYSclk/2/15
    1111                                                                SYSclk/2/16
    (3)ADC转换结果寄存器(ADC_RES,ADC_RESL)
    符号                地址      b7         b6       b5      b4     b3     b2      b1     b0
    ADC_RES       BDH
    ADC_RESL      BEH
    当A/D转换完成后,12位的转换结果会自动保存到ADC_RES和ADC_RESL中。保存结果的数据格式请参考ADC_CFG寄存器中的RESFMT设置。
    (4)ADC时序控制寄存器(ADCTIM)
    符号              地址                b7             b6        b5          b4             b3    b2   b1                   b0
    ADCTIM      FEA8H       CSSETUP     CSHOLD[1:0]                        SMPDUTY[4:0]
    CSSETUP:ADC通道选择时间控制Tsetup
    0:占用1个ADC工作时钟(默认值)
    1:占用2个ADC工作时钟
    (4)ADC时序控制寄存器(ADCTIM)
    符号               地址            b7              b6     b5         b4         b3 b2 b1       b0
    ADCTIM     FEA8H   CSSETUP     CSHOLD[1:0]              SMPDUTY[4:0]
    CSSETUP::ADC通道选择时间控制Tsetup
    0:占用1个ADC工作时钟(默认值)
    1:占用2个ADC工作时钟
    CSHOLD[1:0]:ADC通道选择保持时间控制Thold
    00:占用1个ADC工作时钟
    01:占用2个ADC工作时钟(默认值)
    10:占用3个ADC工作时钟
    11:占用4个ADC工作时钟
    (4)ADC时序控制寄存器(ADCTIM)
    符号                地址              b7          b6   b5            b4           b3b2 b1            b0
    ADCTIM      FEA8H    CSSETUP   CSHOLD[1:0]              SMPDUTY[4:0]
    SMPDUTY[4:0]:ADC模拟信号采样时间控制Tduty
    00000:占用1个ADC工作时钟
    00001:占用2个ADC工作时钟...
    01010:占用11个ADC工作时钟(默认值)
    ...
    11110:占用31个ADC工作时钟
    11111:占用32个ADC工作时钟
    注意:SMPDUTY一定不能设置小于01010B
    (4)ADC时序控制寄存器(ADCTIM)
    ADC数模转换时间:Tconvert为12个ADC工作时钟
    一个完整的ADC转换时间为: T  +Tduty +Thold +T  如下图所示
    1-6.JPG
    (5)ADC扩展配置寄存器(ADCEXCFG)
    符号                   地址          b7    b6    b5       b4            b3         b2    b1      b0
    ADCEXCFG    FEADH                         ADCETRS[1:0]                    CVTIMESEL[2:0] -
    -CVTIMESEL[2:0]:ADC自动转换次数选择
    0xx:转换1次
    100:转换2次并取平均值101:转换4次并取平均值110:转换8次并取平均值
    111:转换16次并取平均值
    注:当使能ADC自动转换多次功能后,ADC中断标志只会在ADC自动转换到设置的次数后,才会被置1(例如:设置CVTIMESEL为101B,即ADC自动转换4次并取平均值,则ADC中断标志位每完成4次ADC转换才会被置1)
    31/32
    一、ADC相关计算公式
    1、ADC速度计算公式
    1-7.JPG
    注意:
    12位ADC的速度不能高于800KHz
    SMPDUTY的值不能小于10,建议设置为15
    CSSETUP可使用上电默认值0
    CHOLD可使用上电默认值1(ADCTIM建议设置为3FH)
    2、ADC转换结果计算公式
    1-8.JPG
    3、反推ADC输入电压计算公式
    1-9.JPG
    4、反推工作电压计算公式
    当需要使用ADC输入电压和ADC转换结果反推工作电压时,若目标芯片无独立的ADC_Vref+管脚,则可直接测量并使用下面公式,若目标芯片有独立ADC_Vref+管脚时,则必须将ADC_Vref+管脚连接到Vcc管脚。
    1-10.JPG
    二、ADC的应用
    AD-3 1、编程步骤
    ■设置相关I/O的工作模式(高阻输入)
    ■设置ADC内部时序,ADC采样时间建议设最大值(ADCTIM)
    ■设置ADC时钟(ADCCFG)
    ■使能ADC模块(ADC_CONTR)
    ■动AD转换
    ■取结果
    ■清除标志位
    二、ADC的应用
    2、实例:NTC测温并显示
    ■ 读ADC
    ■测温度时,使用12位的ADC值,使用对分查找表格来计算,小数点后一位数是用线性插补来计算
    1-11.JPG

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-8 20:44:05 | 显示全部楼层
    9月日,何宾老师:

    设计实例(一)
    1-1.JPG
    设计实例(二)
    【例8—11】不同指针类型转换的C语言描述(一)
    #include"stdio.h"                                         //包含头文件stdio.h
    #include "reg251s.h"                                        //包含头文件reg251s.h
    void main()                                                                //定义main主函数
    {
    volatile intxdata a;                                  //声明整型变量a,位于xdata空间
    volatile charxdata b;                          //声明字符型变量b,位于xdata空间
    volatile intfar *p2;                                       //声明整型指针变量*p2,类型为far
    volatile charfar *p3;                                  //声明字符型指针变量*p3,类型为far
    SCON= 0x52;                                                  //初始化串口寄存器SCON
    TMOD=0x20;                                           //初始化串口寄存器TMOD
    TCON=0x69;                                                  //初始化串口寄存器TCON
    TH1=0xF3;                                                          //初始化串口寄存器TH1
    函数
    C251编译器为标准C函数声明提供了很多扩展
    这些扩展包括:
    ■将函数声明为中断过程
    ■设置寄存器组
    ■选择存储器模型
    ■声明可重入函数
    ■声明外来函数
    程序开发人员可以在函数声明中包含这些扩展或属性(许多可以
    进行组合)
    使用下面的格式声明函数:
    [return_type]funcname ([args]) [{small |large}]
    [_attribute_((attrib_spec))][reentrant]
    [interrupt n]
    [using y]
    其中:
    return_type是从函数返回值的类型。如果没有指定类型,假定为int
    funcname是函数的名字
    args是函数的参数列表
    函数
    存储器模型
    函数参数和局部变量保存在存储器模型指定的默认存储器空间中
    程序开发人员可以通过在函数声明中包含small或large函数属性来指定用于单个函数的存储器模型
    使用SMALL存储器模型的函数的优点在于本地数据和函数参数保存在STC32G系列单片机的片上RAM中。因此,数据访问非常高效。内部存储器是有限的
    有时,small模型不能满足非常大的程序的要求,必须使用其他存储器模型。对于这种情况,程序开发人员可以声明函数使用不同的存储器模型
    函数
    -存储器模型
    通过在函数声明中指定函数模型属性,可以选择使用两个可能的可重入堆栈和帧指针中其中一个。在SMALL模型中堆栈访问比LARGE模型中的更有效
    注:C251版本2或更高版本提供#pragma函数命令。使用该指命令,程序开发人员可以为一个或多个函数单独指定模型或可重入属性,而无需修改函数声明
    函数
    寄存器组
    在STC32G系列单片机中,DATA存储器的前32个字节(0x00~0x1F)被分为4组,每组8个寄存器
    程序以RO~R7的形式访问这些寄存器。寄存器组由程序状态字PSW的两位选择
    当处理中断或使用实时操作系统时,寄存器组非常有用,因为单片机可以为任务或中断切换到不同的寄存器组,而不是保存堆栈上的所有8个寄存器。然后,单片机可以在返回之前将切换到原始寄存器组
    函数
    寄存器组
    using函数属性指定函数使用的寄存器组。比如:
    voidrb_function (void) uring 3
    {
                  ………………..
    }
    using属性的参数是0~3之间的整数常数
    不允许使用带运算符的表达式
    在函数原型中不允许使用using属性
    using属性影响函数的目标代码如下:
    当前选择的寄存器组保存在函数入口的堆栈上
    设置指定的寄存器组
    函数
    寄存器组
    注:using属性不能用于在寄存器中返回值的函数中。程序开发人员必须格外小心,确保寄存器组切换仅在精心控制的区域进行。否则,可能产生错误的函数结果。即使使用相同的寄存器组,使用using属性声明的函数也不能返回位值
    using属性在中断函数中最有用
    通常为每个中断优先级指定不同的寄存器组
    程序开发人员可以为所有非中断代码分配一个寄存器组。为高级中断分配第二个寄存器组和为低级中断分配第三个寄存器组
    函数
    中断函数
    STC32G系列单片机提供了大量的硬件中断,可用于计数器、定时器、检测外部事件以及使用串口发送和接收数据
    C251编译器支持最多32个中断(0~31)的中断函数!!!!
    对于多于32个中断的其他中断,使用STC公司提供的工具进行特殊处理。
    函数
    中断函数
    interrupt函数属性指定相关的函数是一个中断服务例程
    (InterruptService Routine,ISR)
    unsigned intinterruptcnt;
    unsigned chardata second;
    void timer0(void) interrupt 1 using 2
    {
    if (++interruptcnt ==4000)                     //计数到400
    {
    second++;                                              //第二个计数器
    interruptcnt=0;                                  //清除计数器
    }
    函数
    中断函数
    Interrupt属性将值在0~31范围内的整数常数作为参数函数原型中不允许使用带有运算符和中断属性的表达式
    interrupt属性影响函数的目标代码如下:
    当需要时,ACC、B、DPH、DPL、PSW和PSW1的内容将在函数调用时 保存在堆栈中
    如果未使用using属性指定寄存器组,则中断函数中使用的所有工作寄存器都将保存在堆栈中
    退出函数之前,将恢复保存在堆栈中的工作寄存器和特殊寄存器
    在使用汇编语言编写ISR时,中断函数的末尾需要使用RETI指令,表示该中断函数从中断返回
    函数
    中断函数
    下面的规则适用于中断函数,包括:
    无法传递参数。当中断程序中包含任何参数声明时,编译器会发出错误消息
    中断函数声明不能包含返回值。它们必须声明为void。如果尝试定义中断函数的返回值,则编译器会发出错误消息。返回类型void应用于所有中断程序声明。但是编译器会忽略隐含int返回值
    编译器识别对中断函数的直接调用并拒绝它们。使用RETI指令退出中断程序。RETI恢复PSW1的值并影响STC32G系列单片机的中断系统。不要通过函数指针间接调用中断函数
    编译器为每个中断函数生成一个中断向量。为向量生成的代码是跳转到中断函数的开头。通过在C251命令行中使用C251命令NOINTVECTOR,可以抑制中断向量的生成。在这种情况下,必须从单独的汇编程序模块中
    函数
    中断函数
    {>2→ C251编译器允许范围为0~31的中断号
    由于大多数C251库函数都是完全可重入的,因此对调用这些函数没有任何限制。C251在堆栈中为自动变量使用可重入代码。因此,程序开发人员可以调用任何使用reentrant属性编译的C251函数,或者在函数执行期间只使用寄存器
    C251从不为寄存器访问生成绝对地址。每个C251函数独立于实际使用的寄存器组。不再需要C51编译器中已知的NOAREGS命令
    注:有时,删除using属性并让C251编译器PUSH(入栈)使用的寄存器会更有效。这也节省了额外寄存器组所需要的数据存储器。程序开发人员可以将使用或不使用属性生成的代码与C251 CODE命令进行比较
    函数
    -可重入函数
    可重入函数可以同时由多个进程共享
    当一个可重入函数正在执行时,另一个进程可以中断执行,然后开始执行相同的可重入功能
    默认情况下,C251编译器生成静态代码,这意味着函数通常不能递归调用或以导致可重入的方式调用
    静态代码的优点是函数参数和局部变量保存在固定的存储位置,这允许STC32G系列单片机快速访问变量
    函数属性reentrant允许程序开发人员声明可重入的函数,因此可以递归调用
    函数
    -可重入函数
    Int calc(char i,int b) reentrant
    {
    int x; x=table ;
    return(x*b);
    }
    #pragmaFUNCTIONS(reentrant)                   //C251生成可重入CODE
    int func (unsigned char index)
    {
    return(table[index]);
      }
    #pragmaFUNCGONS (static)                                  //再次选择静态CODE
    函数
    -可重入函数
    重入函数可以递归调用,也可以由两个或多个进程同时调用
    在实时应用中,或者在中断代码和非中断代码必须共享一个函数的情况下,通常需要重入函数
    与上面的代码一样,程序开发人员可以选择性地(使用reentrant属性或者FUNCTIONS命令)将函数定义为可重入函数
    重入代码使用STC32G系列单片机的硬件堆栈区作为非寄存器参数和自动变量
    函数
    --可重入函数
    对于可重入函数,由于STC32G系列单片机硬件架构,存在一些限制
    包括:
    不能使用位类型参数。本地位标量也不可用。可重入功能不支持位可寻址变量
    不能从外来函数(alien function)调用可重入函数。重入代码不能使用alien属性,因为PL/M—51参数传递仅是静态的
    注:访问使用STC32G系列单片机硬件堆栈的变量要比访问静态存储器慢。因此,仅在需要时使用可重入函数
    函数
    -外来函数
    C251编译器可轻松与Intel PL/M—51编译器接口,并允许程序开发人员:
    从C调用PL/M—51例程从PL/M—51调用C例程
    要从C函数调用PL/M—51例程,必须使用alien(外来)函数类型说明符将它们声明位外部
    函数
    -外来函数
    C251编译器可轻松与Intel PL/M—51编译器接口,并允许程序开发人员:
    从C调用PL/M—51例程从PL/M—51调用C例程
    要从C函数调用PL/M—51例程,必须使用alien(外来)函数类型说明符将它们声明位外部
    函数
    --外来函数
    extern alienchar plm_func (int, char);
    charc_func(void)
    {
    int i;
    char c;
    for (i=0; i< 100; i++)
    {
    c=plm_func (i,c);                           //调用PL/M函数
    }
    return (c);
    }
    函数
    -外来函数
    要创建可以从PL/M例程调用的C函数,必须在C函数声明中使用alien函数类型说明符。比如:
    alien charc_func (char a, int b)
    {
    return (a*b);
    }
    PL/M-51函数的参数和返回值可以是bit、char、unsigned char、int 和unsigned int。其他类型(包括long、float和所有类型的指针)可以 在C函数中使用alien类型说明符声明。但是,请谨慎使用这些类型,因为PL/M—51不直接支持32位二进制整数或浮点数
    PL/M—51模块中声明的公共变量可用于C程序,方法是将它们声明为外部变量,就像对汪何C变量一样
    函数
    -外来函数
    C251编译器支持带有_task_和_priority_关键字的 RTX251 FULL和RTX251 Tiny实时多任务操作系统
    其中:
    task_关键字指定函数是实时任务priority_关键字指定任务的优先级
    比如:
    void func(void)_task_num_priority_pri
    其中,
    num为任务ID号,对于RTX51 Full为0~255;对于RTX251 Tiny为 0~15
    pri是任务的优先级
    注:任务函数必须使用void返回类型和void参数列表
    函数
    -函数参数
    C函数可以传递寄存器和/或固定存储器位置中的参数■REGPARMS和NOREGPARMS命令使能/禁止使用寄存器传递 参数
    如果禁止使用寄存器传递参数,或者传递的参数套多而无法装入寄存器,则在固定存储器位置传递参数
    通常,使用寄存器参数
    函数参数
    -存储器传递
    传递到固定存储器位置的汇编程序例程的参数使用名字为?function_name?BYTE和?function_name?BIT保存 传递给函数function_name的参数值
    在调用函数之前,位参数被复制到?function_name?BIT段。所有其他参数都复制到?function_name?BYTE段
    即使使用寄存器传递参数,所有参数也会在这些段中分配空间。参数按照在每个段中声明的顺序保存
    用于参数传递的固定存储器位置可以是存储器类DATA、EDATA或XDATA,具体取决于所使用的存储器模型
    函数参数
    -用寄存器传递
    C251编译器使用寄存器R11和R0~R7进行参数传递寄存器中最多可以传递9个参数
    所有其他参数都使用固定存储器位置或STC32G系列单片机内的硬件堆栈传递(取决于函数reentrant/static属性)
    函数参数
    -用寄存器传递
    C251编译器使用寄存器R11和R0~R7进行参数传递■寄存器中最多可以传递9个参数
    所有其他参数都使用固定存储器位置或STC32G系列单片机内的硬件堆栈传递(取决于函数reentrant/static属性)
    函数参数
    -用寄存器传递
    1-2.JPG
    函数参数
    -用寄存器传递
    1-3.JPG
    1-4.JPG
    函数参数
    -函数返回值
    对于传递给C51函数的参数;寄存器R1/R2/R3中返回3字节指针。大小为[1..8]的结构返回类型返回到寄存器RO~R7中,最后一个结构元素的LSB始终以R7结尾
    例如,在R5、R6和R7中返回3字节的结构值。大小为5的结构返回到R3、R4、R5、R6和R7
    包含超过8个字节的结构在内部memcpy函数的帮助下返回目的地址必须在DR12的调用时传递给函数
    函数
    -使用SRC命令
    SRC命令指导编译器生成汇编程序而不是目标模块
    这样,程序开发人员可以使用该命令生成汇编语言源文件的外壳,或者帮助他们确定编译器期望的参数传递规约
    要创建汇编源文件,必须在C251编译器中使用SRC命令,如下:
    --使用SRC命令
    #pragma SRC                                        //SRC命令生成汇编器输出
    #pragma XTINY                                 //指定要使用的存储器模型
    unsigned intasmfunc1 (unsigned int arg)
    {
    return (1+arg);
    {

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-11 19:27:30 | 显示全部楼层
    9月11日,陈老师讲述关于脉冲宽度调制(PWM):

    PWM概述
    脉冲宽度调制(PWM)是利用微处理器的数字输出对模拟电路进行控制的一种非常有效的技术,广泛应用于测量、通信、功率控制与变换等许多领域中。通过使用高分辨率计数器,输出方波的占空比被调制,用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有,要么完全无。
    WidthModetatro 典型的PWM波形如图10—1所示。图中的T为周期,占空比为t/T。
    1-1.JPG
    PWM的应用场景
    1.PWM应用场景之一
    1-2.JPG
    1-3.JPG
    利用占空比的变化,改变舵机转轴的角度。方波脉冲信号的周期为20ms,当方波脉冲宽度改变时,舵机转轴的角度发生变化,角度变化与脉冲宽度的变化成正比。
    2.PWM应用场景之二
    1-4.JPG
    电机驱动
    电路连接好后,用一个逻辑输出的信号来控制马达。高电平(逻辑1)让继电器导通,马达转动;低电平(逻辑0)让继电器断开,马达停止。
    1-5.JPG
    在电路相同的情况下,把马达的“极性”反过来接,可以控制马达的反转,断开继电器就能控制停止。
    问题来了:
    如果我们要同时需要马达能够正转和反转,怎么办?
    想要同时控制正反向的话,就需要更多的电路—最简单的就是H桥电路。H桥电路的“H”的意思是它实际电路在电路图上是一个字母H的样式。
    1-6.JPG
    晶体管代替继电器
    1-7.JPG
    电机驱动
    先来看一个概念:马达速度。如果在其中一种状态下,频繁的切换开关状态,马达的转速就不再是匀速,而是变化的了,相应的扭矩也会改变。通常反应出来的是马达速度的变化。
    1-8.JPG
    电机驱动
    PWM控制
    1-9.JPG 1、STC8H8K64U单片机的PWM模块概述STC8H8K64U单片机内部集成了8通道16位高级PWM定时器,可对外输出任意频率以及任意占空比的PWM波形,分成两组,分别命名为第一组PWM(称为PWMA)和第二组PWM(称为PWMB),它们的周期可分别单独设置(可以不同)。PWMA可配置成4组带死区控制的互补对称PWM或捕捉外部信号,PWMB可配置成4路PWM输出或捕捉外部信号。
    STC8H8K64U单片机的PWM能捕获外部输入信号,可捕获上升沿、下降沿或者同时捕获上升沿和下降沿,测量外部波形时,可同时测量波形的周期值和占空比值。有正交编码功能、外部异常检测功能以及实时触发ADC转换功能。
    PWMA有4个通道(分别为PWM1P/PWM1N、PWM2P/PWM2N、 PWM3P/PWM3N、PWM4P/PWM4N),每个通道都可独立实现PWM输出(可 设置为带死区的互补对称PWM输出)、捕获和比较功能。
    PWMB有4个通道(分别为PWM5、PWM6、PWM7、PWM8),每个通道 也可独立实现PWM输出、捕获和比较功能。
    两组PWM定时器唯一的区别是第一组可输出带死区的互补对称PWM,而第二组只能输出单端的PWM,其他功能完全相同。
    2、STC8H8K64U单片机PWM模块的功能
    (1)PWM波形的输出
    当使用第一组PWM定时器输出PWM波形时,可单独使能PWM1P/PWM2P/PWM3P/PWM4P输出(称为P端输出),也可单独使能 PWM1N/PWM2N/PWM3N/PWM4N输出(称为N端输出)。可选择的输出规则 如下:
    1)P端输出和对应的N端输出不能同时独立输出。例如,若单独使能了PWM1P输出,则PWM1N就不能再独立输出,除非PWM1P和PWM1N组成一组互补对称输出。
    2)PWMA的4路输出是可分别独立设置的,例如:可单独使能PWM1P和PWM2N输出,也可单独使能PWM2N和PWM3N输出。
    2、STC8H8K64U单片机PWM模块的功能
    (2)捕获功能或者脉宽测量
    若需要使用第一组PWM定时器进行捕获功能或者测量脉宽时,输入信号只能从每路的正端输入,即只有PWM1P/PWM2P/PWM3P/PWM4P才有捕获功能和测量脉宽功能。
    两组高级PWM定时器对外部信号进行捕获时,可选择上升沿捕获或者下降沿捕获。如果需要同时捕获上升沿和下降沿,则可将输入信号同时接入到两路PWM,使能其中一路捕获上升沿,另外一路捕获下降沿。将外部输入信号同时接入到两路PWM时,可同时捕获信号的周期值和占空比值。
    3、STC8H8K64U单片机PWM模块的性能
    (1)16位向上、向下、向上/下自动装载计数器。
    (2)允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器。
    (3)16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数
    为1~65535之间的任意数值。
    (4)同步电路,用于使用外部信号控制定时器以及定时器互联。
    (5)多达4个独立通道可以配置成:
    ·输入捕获
    ·输出比较
    ·PWM输出(边缘或中间对齐模式)
    ·六步PWM输出
    ·单脉冲模式输出
    ·PWMA支持4个死区时间可编程的通道上互补输出
    (6)刹车输入信号(PWMFLT)可以将定时器输出信号置于复位状态或者
    一个确定状态。
    (7)外部触发输入引脚(PWMETI)。
    (8)PWMA/PWMB各有8个中断请求源:
    ·刹车中断(刹车信号输入)
    ·触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
    ·COM事件中断
    ·输入捕捉/输出比较1~4中断
    ·更新事件中断:计数器向上溢出/向下溢出或计数器初始化(通过软件
    或者内部/外部触发)
    9/28
    PWM的时基单元
    1.时基单元的结构图
    1-10.JPG
    自动重载寄存器由预装载寄存器和影子寄存器组成。可在下面两种模式下写自动重载寄存器:
    (1)自动预装载已使能(PWMA_CR1寄存器的ARPE位为1)。在此模式下,写入自动重载寄存器的数据将被保存在预装载寄存器中,并在下一个更新事件(UEV)时传送到影子寄存器。
    (2)自动预装载已禁止(PWMA_CR1寄存器的ARPE位为0)。在此模式下,写入自动重载寄存器的数据将立即写入影子寄存器。
    产生更新事件的条件有:
    (1)计数器向上或向下溢出。
    (2)软件置位了PWMA_EGR寄存器的UG位。(3)时钟/触发控制器产生了触发事件。
    2.16位计数器的读写操作
    写计数器的操作没有缓存,在任何时候都可以写PWMA_CNTRH和PWMA_CNTRL寄存器,因此为避免写入了错误的数值,一般建议不要在计数器运行时写入新的数值。
    读计数器的操作带有8位的缓存。用户必须先读定时器的高字节,在用户读了高字节后,低字节将被自动缓存,缓存的数据将会一直保持直到16位数据的读操作完成。
    1-11.JPG
    4.预分频器
    PWMA的预分频器是一个由16位寄存器(PWMA_PSCR)控制的16位计数器。这个控制寄存器带有缓冲器,因此,它可以在运行时被改变。预分频器可以将计数器的时钟频率按1到65536之间的任意值分频。
    计数器的频率计算公式:
    fck_CNT=fck_psc/(PSCR[15:0]+1)
    PWMA模块的计数模式
    1.向上计数模式
    在向上计数模式中,计数器从0计数到用户定义的比较值(PWMA_ARR寄存器的值),然后重新从0开始计数并产生一个计数器溢出事件(上溢),此时如果PWMA_CR1寄存器的UDIS位是0,将会产生一个更新事件(UEV)。
    1-12.JPG
    假设PWMA_ARR=0x36,当ARPE=0(ARR不预装载),预分频为2时的计 数器更新情况。
    2.向下计数模式
    在向下模式中,计数器从自动装载的值(PWMA_ARR寄存器的值)开始向下计数到0,然后再从自动装载的值重新开始计数,并产生一个计数器向下溢出事件(下溢)。如果PWMA_CR1寄存器的UDIS位被清除,还会产生一个更新事件(UEV)。
    1-13.JPG
    在向下计数模式下,假设PWMA_ARR=0x36,当ARPE=0(ARR不预装载),预分频为2时的计数器更新情况。
    3.中间对齐模式(向上/向下计数模式)
    在中央对齐模式,计数器从0开始计数到PWMA_ARR寄存器—1,产生一个计数器上溢事件,然后从PWMA_ARR寄存器的值向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。在此模式下,不能写入PWMA_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。
    1-14.JPG
    1-15.JPG
    使用中央对齐模式应该注意:
    (1)启动中央对齐模式时,计数器将按照原有的向上/向下的配置计数。也就是说PWMA_CR1寄存器中的DIR位将决定计数器是向上还是向下计数。此外,软件不能同时修改DIR位和CMS位的值。
    (2)不推荐在中央对齐模式下,计数器正在计数时写计数器的值,这将导致不能预料的后果。
    (3)安全使用中央对齐模式的计数器的方法是在启动计数器之前先用软件(置位PWMA_EGR寄存器的UG位)产生一个更新事件,并且不在计数器计数时修改计数器的值。
    使用中央对齐模式应该注意:
    (1)启动中央对齐模式时,计数器将按照原有的向上/向下的配置计数。也就是说PWMA_CR1寄存器中的DIR位将决定计数器是向上还是向下计数。此外,软件不能同时修改DIR位和CMS位的值。
    (2)不推荐在中央对齐模式下,计数器正在计数时写计数器的值,这将导致不能预料的后果。
    (3)安全使用中央对齐模式的计数器的方法是在启动计数器之前先用软件(置位PWMA_EGR寄存器的UG位)产生一个更新事件,并且不在计数器计数时修改计数器的值。
    4.重复计数器
    时基单元解释了计数器向上/向下溢出时更新事件(UEV)是如何产生的,然而事实上它只能在重复计数器的值达到0的时候产生。这个特性对产生PWM信号非常有用。
    这意味着在每N次计数上溢或下溢时,数据从预装载寄存器传输到影子寄存器(PWMA_ARR自动重载入寄存器,PWMA_PSCR预装载寄存器,还有在比较模式下的捕获/比较寄存器PWMA_CCRx),N是PWMA_RCR重复计数寄存器中的值。
    重复计数器在下述任一条件成立时递减:
    (1)向上计数模式下每次计数器向上溢出时;(2)向下计数模式下每次计数器向下溢出时;
    (3)中央对齐模式下每次上溢和每次下溢时。
    重复计数器是自动加载的,重复速率由PWMA_RCR寄存器的值定义。如果更新事件由软件产生或者通过硬件的时钟/触发控制器产生,则无论重复计数器的值是多少,立即发生更新事件,并且PWMA_RCR寄存器中的内容被重载入到重复计数器。
    不同模式下,不同的PWMA_RCR存器设置时,计数器更新速率。
    1-16.JPG

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-12 19:49:01 | 显示全部楼层
    9月12日,何宾老师讲述:
    函数参数
    用寄存器传递
    C251编译器使用寄存器R11和R0~R7进行参数传递
    寄存器中最多可以传递9个参数
    所有其他参数都使用固定存储器位置或STC32G系列单片机内的
    硬件堆栈传递(取决于函数reentrant/static属性)
    可重入函数/递归函数的C语言描述
    在该设计中,使用递归算法实现斐波那契数列
    即满足下面的条件:
    (f(1)=1, O
    {f(2)=1,
    (f(n)Ff(n-1)+f(n-2),n>2
    函数-存储器模型
    函数参数和局部变量保存在存储器模型指定的默认存储器空间中

    程序开发人员可以通过在函数声明中包含small或large函数属性来指定用于单个函数的存储器模型
    使用SMALL存储器模型的函数的优点在于本地数据和函数参数保存在STC32G系列单片机的片上RAM中。因此,数据访问非常高效。内部存储器是有限的
    有时,small模型不能满足非常大的程序的要求,必须使用其他存储器模型。对于这种情况,程序开发人员可以声明函数使用不同的存储器模型
    属性--alias(“target" )
    使用该属性为变量和函数指定多个别名
    如果在当前翻译单元中定义了变量或函数,则别名引用将替换为对变量或函数的引用,别名将与原来的名字一起发出
    如果在当前翻译单元中没有定义变量或函数,则别名引用将替换为对实际变量或函数的引用
    如果将变量或函数定义为static,则用别名替换变量或函数名字如果别名被声明为外部,则该变量或函数声明为外部
    属性-alias(“target" )
    变量alias属性的C语言描述
    int a=100;                                                                                    //声明并初始化全局整型变量a
    int b=200;                                                                  //声明并初始化全局整型变量b
    extern int x_attribute_((alias("a")));      //给整型变量a起别名为x
    extern int y_attribute_((alias("b")));     //给整型变量b起别名为y
    voidmain(void)                                                                //定义main主函数
    {
    volatile intz;                                                          //声明整型变量z
    file:///C:/Users/yy/AppData/Local/Temp/msohtmlclip1/01/clip_image001.gifz=x+y;                                                       //x+y ---z
    while(1);                                                                   //无限循环,设置断点
    属性-alias(“target" )
    函数alias属性的C语言描述
    charcomp(char a, char b)_attribute_((alias("add")));
    char add(char a,char b)
    {
    return(a+b);
    }
    voidmain(void)
    {
    volatile char x;
    x=comp(10,20);
    while(1);
    属性-aligned(n)
    aligned(n)是一个变量和函数属性,用于指定变量、结构体字段或函数的最小对齐方式
    n以字节为单位指定对齐方式
    aligned属性优先于命令ORDER
    关键字_at覆盖对齐属性
    属性-aligned(n)
    aligned属性的C语言描述
    struct num{                       //定义结构体num
    char a_attribute_((aligned(2)));                            //定义字符变量a,2字节对齐
    int      b_attribute_((aligned(4)));                     //定义字符变量b,4字节对齐     
    long int c_attribute_((aligned(8)));               // 定义字符变量c,8字节对齐
    char         d;                                                             //定义字符变量d
    };
    属性-noreturn
    noreturn是一个函数属性,用于通知编译器该函数永远不会返回
    然后编译器可以优化并生成更好的代码
    更重要的是,它有助于避免未初始化变量的虚假警告
    不要假设在调用noreturn函数之前,调用函数保存的寄存器已恢复
    noreturn函数的返回类型应该为void 该属性在C251版本5.51中实现
    预处理器
    C251编译器中内置的预处理器处理源文件中的命令
    C251编译器支持所有美国国家标准学会(American National
    StandardsInstitute,ANSI)标准C命令
    预处理是编译器执行的第一个操作
    预处理器的目的是在编译之前替换或插入额外的文本到源文件
    预处理器
    大多数预处理器函数需要通过在源代码中包含预处理器命令来激活
    然而,预处理器总是
    用单个空格代替每个C注释
    删除行延续符(由行末尾的反斜杠(“\”)表示),并连接分开的行以进行编译
    用预定义的文本代替预定义的宏名字
    预处理器
    头文件
    头文件或包含文件由预处理器包含和处理
    #include命令告诉C预处理器包含编译器输入流中指定的文件内容,然后继续处理原始文件的其余文件
    通常,头文件包含变量和函数声明以及宏定义
    但是,它们不局限于这些。头文件可以包含任何有效的C程序片段。然而,这种做法容易出错,非常混乱,不建议使用
    头文件通常包含其他头文件的#include命令
    因此,某些头文件可能会被包含多次。如果这些头文件定义了结构、typedef、程序代码或变量,那么编译器可能会生成错误或警告
    预处理器
    头文件
    为了避免更频繁地包含头文件,请在预处理文件中有条件包含头文件的内容
    例如:
    #ifndefFILENAME INCLUDED
    #defineFILENAME INCLUDED
    /*Header FileContent*/
    #endif
    当定义了FILENAME_INCLUDED时,表示已经包含头文件FILENAME
    根据C标准(ISO/IEC9899:1990),对于系统头文件,宏名字以“_”开头,对于用户头文件不应以”-”开头。宏名字应包
    预处理器---头文件
    包含头文件的C语言描述
    头文件header.h#ifndef SYMBOL
    #define SYMBOL
    int a=10,b=20;
    #endif
    预处理器_宏
    宏允许程序开发人员为源代码块指定短名字
    在源文件中使用宏名字时,预处理器会将其替换为宏定义中指定的源代码块
    宏定义包括宏的名字、宏体,以及可以包含宏参数
    简单宏不要求参数,是定义的最简单宏
    复杂宏接受一个或多个参数,可以像函数一样使用
    宏运算符列表列出了宏定义中可能使用的特殊宏运算符
    预定义的宏列出编译器在编译时定义的宏
    宏--简单宏
    简单的宏只是代码片段的缩写
    通常将其称为清单常数因为它定义了常数值的名字。在使用宏之前,必须使用#define命令定义宏,比如:
    #define LEN 128
    它定义了名字为LEN的宏
    当在程序中(或在预处理命令中)使用LEN时,它将使用文本128进行替换,比如
    char buffer[N];
    被预处理器扩展为
    char buffer[128];
    宏-----复杂宏
    复杂宏接受参数,并使用这些参数的值生成代码片段接受参数的宏看上去很像函数。但是,参数类型与C函数不同它们仅在展开时由传递给宏的文本替换
    与简单宏一样,必须使用#define命令定义带参数的宏,然后才能使用它们。参数列表用括号括起来,必须紧跟在宏名字的后面
    宏名字和左括号之间不能有空格
    例如:
    #defineMAX(x,y) ((x)>(y)?(x):(y))
    定义了一个名字为MAX的宏,它接受两个参数x和y
    宏-复杂宏
    当程序中(或预处理器指令)使用MAX时,将其替换为文本((x)>(y)?(x):(y))
    如果x和y是数值常量,则预处理器可以确定宏的结果并替换较大的值
    一个类似下面的C语言
    int a=MAX(15,20);
    由预处理器扩展为:
    int a=20;
    一个类似下面的C语言
    int a=MAX(myvar,20);
    宏-------复杂宏
    传递给宏的参数个数必须与宏定义中指定的参数个数匹配通常的做法是用括号将宏定义中使用的参数括起来。这样做是为了使复合表达式在传递给宏时不会产生不必要的副作用
    比如:
    #defineMAX(x,y) ((x)> (y)? (x):(y))
    将下面的C语句
    inta=MAX(x-5,10);
    扩展为
    int a =((x-5)> (10)? (x-5):(10));
    宏---复杂宏
    在没有附加括号的情况下,比如
    #defineMAX(x,y)x>y?x:y
    将下面的C语句
    inta=MAX(x-5,10);
    扩展为
    inta=x-5>(10)?x-5:10;
    具有潜在不同的含义
    宏---复杂宏
    多次使用参数的宏可能会给程序带来不希望的副作用,例如:
    #defineMAX(x,y) ((x)> (y)? (x):(y))
    maxval=MAX(a+b,func(c));
    扩展为
    maxval=((a+b)> (func(c))? (a+b): (func(c)));
    函数func在程序中似乎只能被调用一次,但由于宏的定义,它实际上被调用了两次。每个调用可能返回不同的值,MAX的结果可能不正确
    宏----复杂宏
    支持与C99标准相对应的可变参数宏
    如果宏定义的最后一个参数是...,则宏体中标识符VA_ARGS_的任何出现都将替换为与省略号...匹配的所有参数,包括它们之间的逗号。至少有一个参数必须与省略号匹配
    例如:
    #defineCHECK(v,...)                if (!(v)) printf(_VA_ARGS_)
    CHECK(a==b,"a:%dnot equal b:%d\n",a,b);
    扩展为:
    if (!(a==b))printf("a:%d not equal b:%d\n",a,b);
    宏------宏操作符
    在#define或#if和#elif预处理器命令中可以使用三个预处理器操作符
    字符串化操作符(#)
    标记粘贴操作符(##)
    定义的操作符
    宏操作符—字符串化操作符(#)
    在宏定义中使用字符化串或数字符号操作符('#')时会将宏参数转换为字符串常数
    该操作符只能在具有指定参数或参数列表的宏中使用
    当字符串化操作符紧跟在宏参数之一的名字之前时,传递给宏的参数被括在引号中,并被看作是字符串文字。例如:
    #definestringizer(x) printf(#x"\n")
    stringizer(text)
    上面的代码从预处理器得到以下实际输出:printf(“text\n”)
    宏操作符-----字符串化操作符(#)
    在宏定义中使用字符化串或数字符号操作符('#')时会将宏参数转换为字符串常数
    该操作符只能在具有指定参数或参数列表的宏中使用
    当字符串化操作符紧跟在宏参数之一的名字之前时,传递给宏的参数被括在引号中,并被看作是字符串文字。例如:
    #definestringizer(x) printf (#x "\n") stringizer(text)
    上面的代码从预处理器得到以下实际输出:
    printf(“text\n”)
    宏操作符----字符串化操作符(#)
    展开显示该参数是按字面意思转换的,就像它是一个字符串一样。当预处理器字符串化x参数时,生成的行是:
    printf(“text”“\n”)
    在编译时,将由空格分隔的字符串链接起来。因此,这两个字符串被组合为“text\n”
    如果作为参数传递的字符串包含通常应进行文字化或转义的字符(例如“和\),则会自动添加所需的\字符
    宏操作符—标记粘贴操作符(##)
    宏定义中的标记粘贴操作符(##)组合了两个参数它将宏定义中两个单独的标记连接到单个标记中
    如果宏定义中使用的宏参数的名字前面或后面仅跟着标记粘贴操作符,则宏参数和标记粘贴操作符将替换为传递的参数值
    与不是宏参数名字的标记粘贴操作符相邻的文本不受影响。例如:#define paster(n) printf ("token" #n "= %d", token##n) paster(9);
    上面的代码导致预处理器的下面实际输出:
    printf(“token9=%d”,token9);
    该结果显示标记##n到标记9的并置。该例子中同时使用了字符化
    宏操作符--定义的操作符
    在常量表达式中使用预处理器定义的操作符来确定是否定义了标识符(通过#define预处理器命令)
    如果定义了指定的标识符,则该值为真(非零)。如果未定义符号,则值为假(零)。定义的操作符指定如下:
    defined(identifier)
    definedidentifier
    defined操作符只能用在#if或#elif命令中
    预处理器   -预定义的宏
    C251编译器提供了以下预定义的常数
    常数                                                                  功能
    _C251_                                                      编译器版本号(比如,401对应于版本4.01)
    _DATE_                                                 以ANSI格式开始编译的日期(month dd yyyy)
    _ DATE2_                                                    以短格式开始编译的日期(mm/dd/yy)
    _FILE_                                                                       正在编译的文件名字
    _LINE_                                                                        正在编译的文件中的行号
    _MODEL_                                                    选择的存储器模型。0:SMALL;2: LARGE;3: TINY;
    4:XTINY; 5: XSMALL
    _TIME_                                                                     编译开始的时间
    _STDC_                                                             定义为1表示完全符合ANSI C标准
    _FLOAT64_                            定义为0表示使用32位浮点数。如果通过调用或#pragma给出FLOAT64命令,则定义为1。FLOAT64将浮点运算改为双精度(64位)
    _MODSRC_                      如果通过调用或#praama指定STC32G系列单片机的二讲制模式.则定
    宏调用的例子
    宏的C语言描述 #include"stdio.h"                    //包含头文件stdio.h
    #include"reg251s.h"                                             //包含头文件reg251s.h
    #definemax(a,b) (a>=b?a:b)                                        //定义带有参数的宏max
    #definemin(a,b) (a<=b?a:b)                                 //定义带有参数的宏min
    /**** 定义带有字符串化运算符的宏stringizer ******/
    #definestringizer(x)printf(#x"\n")
    /*******定义带有标记粘贴运算符的宏paster*******/
    #definepaster(n) printf ("a" #n " = %d\n", a##n)
    **********定义可变参数宏CHECK***********/

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-13 20:06:46 | 显示全部楼层
    本帖最后由 ccczzzwwwyy 于 2023-9-15 19:13 编辑

    9月13日,陈老师讲述:

    1、预分频时钟(CK_PSC)的时钟源
    2、捕获/比较通道

    1-1.JPG

    时基单元的预分频时钟(CK_PSC)可以由以下资源提供:
    (1)内部时钟(CK_INT)
    (2)外部时钟模式1:外部时钟输入(TIx)
    (3)外部时钟模式2:外部触发输入ETR
    (4)内部触发输入(ITRx):使用一个PWM的TRGO做为另一个PWM的预分频时钟。

    1、内部时钟源(fMASTER)
    如果同时禁止了时钟/触发模式控制器和外部触发输入(PWMA_SMCR寄存器的SMS=000,PWMA_ETR寄存器的ECE=0),则CEN、DIR和UG位是实际 上的控制位,并且只能被软件修改(UG位仍被自动清除)。一旦CEN位被写成
    1,预分频器的时钟就由内部时钟提供。
    1-2.JPG
    2、外部时钟源模式1
    当PWMA_SMCR寄存器的SMS=111时,选择外部时钟源模式。通过PWMA_SMCR寄存器的TS位选择TRGI的信号源。计数器可以在选定输入端的每个上升沿或下降沿计数。
    1-3.JPG
    2、外部时钟源模式1
    1-4.JPG
    要配置向上计数器在TI2输入端的上升沿计数,使用下列步骤:
    (1)配置PWMA_CCMR2寄存器的CC2S=01,通道2输入选择TI2;
    (2)配置PWMA_CCMR2寄存器的IC2F[3:0]位,选择输入滤波器带宽;
    (3)配置PWMA_CCER1寄存器的CC2P=0,选定上升沿极性;
    (4)配置PWMA_SMCR寄存器的SMS=111,配置计数器使用外部时钟模式1;
    (5)配置PWMA_SMCR寄存器的TS=110,选定TI2作为输入源;
    (6)设置PWMA_CR1寄存器的CEN=1,启动计数器。

    2、外部时钟源模式1
    当上升沿出现在TI2,计数器计数一次,且触发标识位(PWMA_SR1寄存器的TIF位)被置1,如果使能了中断(在FWMA_IER寄存器中配置)则会产生中断请求。
    在TI2的上升沿和计数器实际时钟之间的延时取决于在TI2输入端的重新同步电路。
    1-5.JPG
    3、外部时钟源模式2
    计数器能够在外部触发输入ETR信号的每一个上升沿或下降沿计数。将PWMA_ETR寄存器的ECE位写1,即可选定此模式。(PWMA_SMCR寄存器的 SMS=111且PWMA_SMCR寄存器的TS=111时,也可选择此模式)
    1-6.JPG
    例如,要配置计数器在ETR信号的每2个上升沿时向上计数一次,需使用下列步骤:
    (1)本例中不需要滤波器,配置PWMA_ETR寄存器的ETF[3:0]=0000;
    (2)设置预分频器,配置PWMA_ETR寄存器的ETPS[1:0]=01(频率/2);
    (3)选择ETR的上升沿检测,配置PWMA_ETR寄存器的ETP=0;
    (4)开启外部时钟模式2,配置PWMA_ETR寄存器中的ECE=1;(5)启动计数器,写PWMA_CR1寄存器的CEN=1;

    计数器在ETR信号的每2个上升沿时向上计数一次的实例图
    1-7.JPG 捕获/比较通道

    PWM1P、PWM2P、PWM3P、PWM4P可以用作输入捕获;
    PWM1P/PWM1N、PWM2P/PWM2N、PWM3P/PWM3N、PWM4P/PWM4N 可以输出比较。
    上述功能可以通过配置捕获/比较通道模式寄存器(PWMA_CCMRi)的CCiS通道选择位来实现(其中,i=1,2,3,4)。

    1、捕获/比较通道的结构

    8

    8

    每一个捕获/比较通道都是围绕着一个捕获/比较寄存器(包含影子寄存器)来构建的,包括捕获的输入部分(数字滤波、多路复用和预分频器)和输出部分(比较器和输出控制)。
    捕获/比较模块由一个预装载寄存器和一个影子寄存器组成。读写过程仅操作预装载寄存器。在捕获模式下,捕获发生在影子寄存器上,然后再复制到预装载寄存器中。在比较模式下,预装载寄存器的内容被复制到影子寄存器中然后影子寄存器的内容和计数器进行比较。

    2、对16位寄存器PWMA_CCRi的读写操作
    (1)对PWMA_CCRi寄存器的读操作
    当通道被配置成输入模式时,对PWMA_CCRi寄存器的读操作类似于计数器的读操作。当捕获发生时,计数器的内容被捕获到PWMA_CCRi影子寄存器,随后再复制到预装载寄存器中。(先读高字节)
    1-9.JPG
    3、输入捕获模式
    (1)输入模块的结构
    1-10.JPG
    输入部分对相应的TLx(x=1,2,3,4,下同)输入信号采样,并产生一个滤波后的信号TIxF。然后,经过一个带极性选择的边缘监测器产生信号TLxFPy(y=1,2),该信号作为触发模式控制器的输入触发或者作为捕获控制,通过预分频后进入捕获寄存器(ICxPS)。

    以TI1为例,具体的处理过程框图
    1-11.JPG
    (2)输入捕获模式的工作过程
    在输入捕获模式下,当检测到ICi信号上相应的边沿后,计数器的当前值被锁存到捕获/比较寄存器(PWMA_CCRx)中。
    当发生捕获事件时,PWMA_SR寄存器中的相应CCiIF标志被置1。
    如果PWMA_IER寄存器的CCiIE位被置位,也就是使能了中断,则将产生中断请求。
    如果发生捕获事件时CCiIF标志已经为高,那么PWMA_SR2寄存器中的重复捕获标志CCiOF被置1。写CCiIF=0或读取存储在PWMA_CCRiL寄 存器中的捕获数据都可清除CCiIF。写CCiOF=0可清除CCiOF。

    1)实现PWM输入信号上升沿时捕获的设置
    例如,在TI1输入的上升沿时捕获计数器的值到PWMA_CCR1寄存器中。设置步骤:
    ①选择有效输入端,设置PWMA_CCMR1寄存器中的CC1S=01,此时通道1被配置为输入,并且PWMA_CCR1寄存器变为只读。
    ②根据输入信号TI1的特点,可通过配置PWMA_CCMR1寄存器中的IC1F位来设置相应的输入滤波器的滤波时间。假设输入信号在最多5个时钟周期的时间内抖动,须配置滤波器的带宽长于5个时钟周期,因此,可以连续采样8次,以确认在TI1上一次真实的边沿变换,即在PWMA_CCMR1寄存器中写入IC1F=0011,此时,只有连续采样到8个相同的TI1信号,信号才为有效(采样频率为fMASTER)。

    ③选择TI1通道的有效转换边沿,在PWMA_CCER1寄存器中写入CC1P=0(上升沿)。
    ④配置输入预分频器。在本例中,希望捕获发生在每一个有效的电平转换时刻,因此,预分频器被禁止(写PWMA_CCMR1寄存器的IC1PS=00)。
    ⑤设置PWMA_CCER1寄存器的CC1E=1,允许捕获计数器的值到捕获寄存器中。
    ⑥如果需要,通过设置PWMA_IER寄存器中的CC1IE位允许相关中断请求。

    2)PWM输入信号测量
    该模式是输入捕获模式的一个特例,除下列区别外,操作与输入捕获模式相同:
    ·两个ICi信号被映射至同一个TIi输入。
    ·这两个ICi信号的有效边沿的极性相反。
    ·其中一个TIiFP信号被作为触发输入信号,而触发模式控制器被配置成复位触发模式。

    例如,可以用以下方式测量TI1上输入的PWM信号的周期(PWMA_CCR1寄存器)和占空比(PWMA_CCR2寄存器)。
    ①选择PWMA_CCR1的有效输入:置PWMA_CCMR1寄存器的CC1S=01(选中TI1FP1)。 ②选择TI1FP1的有效极性:置CC1P=0(上升沿有效)。
    ③选择PWMA_CCR2的有效输入:置PWMA_CCMR2寄存器的CC2S=10(选中TI1FP2)。 ④选择TI1FP2的有效极性(捕获数据到PWMA_CCR2):置CC2P=1(下降沿有效)。
    ⑤选择有效的触发输入信号:置PWMA_SMCR寄存器中的TS=101(选择TI1FP1)。⑥配置触发模式控制器为复位触发模式:置PWMA_SMCR中的SMS=100。
    ⑦使能捕获:置PWMA_CCER1寄存器中CC1E=1,CC2E=1。

    例如,可以用以下方式测量TI1上输入的PWM信号的周期(PWMA_CCR1寄存器)和占空比(PWMA_CCR2寄存器)。
    1-12.JPG
    4、输出模式
    (1)输出模块的结构
    1-13.JPG
    输出模块用来产生一个用来做参考的中间波形,称为OCiREF(高有效)。刹车功能和极性的处理都在模块的最后处理。

    4、输出模式
    通道1带互补输出的输出模块框图
    1-14.JPG
    (2)强制输出模式
    在输出模式下,输出比较信号能够直接由软件强制为高或低状态,而不依赖于输出比较寄存器和计数器间的比较结果。
    置PWMA_CCMRi寄存器的OCiM=101,可强制OCiREF信号为高。 置PWMA_CCMRi寄存器的OCiM=100,可强制OCiREF信号为低。

    (3)输出比较模式
    此模式用来控制一个输出波形或者指示一段给定的时间已经达到。当计数器与捕获/比较寄存器的内容相匹配时,有如下操作:
    ①根据不同的输出比较模式,相应的OCi输出信号:
    ·CiM=000时,保持不变
    ·OCiM=001时,设置为有效电平
    ·OCiM=010时,设置为无效电平
    ·OCiM=011时,翻转
    ②设置中断状态寄存器中的标志位(PWMA_SR1寄存器中的CCiIF位)。
    ③若设置了相应的中断使能位(PWMA_IER寄存器中的CCiIE位),则产生一个中断。

    输出比较模式的配置步骤:
    ①选择计数器时钟(内部、外部或者预分频器)。
    ②将相应的数据写入PWMA_ARR和PWMA_CCRi寄存器中。
    ③如果要产生一个中断请求,设置CCiIE位。
    ④选择输出模式,步骤如下:
    ·设置OCiM=011,在计数器与CCRi匹配时翻转OCiM管脚的输出。
    ·设置OCiPE=0,禁用预装载寄存器。
    ·设置CCiP=0,选择高电平为有效电平。
    ·置CCiE=1,使能输出。
    ⑤设置PWMA_CR1寄存器的CEN位启动计数器。

    (4)PWM模式
    由于仅当发生一个更新事件的时候,预装载寄存器才能被传送到影子寄存器,因此,在计数器开始计数之前,必须通过设置PWMA_EGR寄存器的UG位来初始化所有的寄存器。
    OCi的极性可以通过软件在PWMA_CCERi寄存器中的CCiP位设置,它可以设置为高电平有效或低电平有效。OCi的输出使能通过PWMA_CCERi和PWMA_BKR寄存器中的CCiE、MOE、OISi、OSSR和OSSI位的组合来控制。 在PWM模式(模式1或模式2)下,PWMA_CNT和PWMA_CCRi始终在进行 比较,(依据计数器的计数方向)以确定是否符合PWMA_CCRi≤PWMA_CNT或者PWMA_CNT≤PWMA_CCRi。

    (4)PWM模式
    ①向上计数配置(PWMA_CR1寄存器中的DIR位为0)
    假设ARR=8,边沿对齐的PWM模式1
    1-15.JPG
    (4)PWM模式
    计数器寄存题
    ③PWM中央对齐模式, 当PWMA_CR1寄存器中的CMS 位不为'00'时为中央对齐模式。
    PWMA_ARR=8,PWM模式1,中央对齐的PWM波形图

    16

    16


    1、输出使能寄存器(PWMx_ENO)
    1-17.JPG -
    ENOIP:PWMiP输出控制位。0:禁止PWMiP输出;1:使能PWMiP输出。 i=1,2,3,...,8
    ENOjN:PWMjN输出控制位。 0:禁止PWMjN输出;1:使能PWMjN输出。 j=1,2,3,4

    2、控制寄存器1(PWMx_CR1)
    1-18.JPG
    ARPEn:自动预装载允许位(n=A,B,下同)
    0:PWMn_ARR寄存器没有缓冲,它可以被直接写入。1:PWMn_ARR寄存器由预装载缓冲器缓冲。
    CMSn[1:0]:选择对齐模式
    00:边沿对齐模式,计数器依据方向位(DIR)向上或向下计数。
    01:中央对齐模式1,计数器交替地向上和向下计数。配置为输出的通道,其输出的比较中断标志位只在计数器向下计数时被置1。
    10:中央对齐模式2,计数器交替地向上和向下计数。配置为输出的通道,其输出的比较中断标志位只在计数器向上计数时被置1。
    11:中央对齐模式3,计数器交替地向上和向下计数。配置为输出的通道,其输出的比较中断标志位在计数器向上和向下计数时均被置1。

    2、控制寄存器1(PWMx_CR1)
    1-19.JPG
    DIRn:计数器的计数方向位。
    0:计数器向上计数;
    1:计数器向下计数。
    注:当计数器配置为中央对齐模式或编码器模式时,该位为只读。OPMn:单脉冲模式控制位。
    0:在发生更新事件时,计数器不停止;
    1:在发生下一次更新事件时,清除CEN位,计数器停止。

    2、控制寄存器1(PWMx_CR1)
    1-20.JPG
    URSn:更新请求源
    0:如果UDIS允许产生更新事件,则下述任一事件产生一个更新中断:
    —寄存器被更新(计数器上溢/下溢)
    -软件设置UG位
    —时钟/触发控制器产生的更新
    1:如果UDIS允许产生更新事件,则只有寄存器被更新(计数器上溢/下溢)时才产生更新中断,并UIF置1。

    2、控制寄存器1(PWMx_CR1)
    1-21.JPG
    UDISn:禁止更新控制位。
    0:一旦下列事件发生,产生更新(UEV)事件:
    -计数器溢出/下溢
    -产生软件更新事件
    —时钟/触发模式控制器产生的硬件复位 被缓存的寄存器被装入它们的预装载值。
    1:不产生更新事件,影子寄存器(ARR、PSC、CCRx)保持它们的值。如果设置了UG位或时钟/触发控制器发出了一个硬件复位,则计数器和预分频器被重新初始化。

    2、控制寄存器1(PWMx_CR1)
    1-22.JPG
    CENn:允许计数器控制位。
    0:禁止计数器;                         1:使能计数器。
    注:在软件设置了CEN位后,外部时钟、门控模式和编码器模式才能工作。然而,触发模式可以自动地通过硬件设置CEN位。

    3、控制寄存器2(PWMx_CR2)
    1-23.JPG TI1S:PWMA的TI1选择位。
    0:PWM1P输入引脚连到TI1(数字滤波器的输入);
    1:PWM1P、PWM2P和PWM3P引脚经异或后连到PWMA的TI1。
    TI5S:PWMB的TI5选择位。
    0:PWM5输入引脚连到TI5(数字滤波器的输入);
    1:PWM5、PWM6和PWM7引脚经异或后连到PWMB的TI5。

    3、控制寄存器2(PWMx_CR2)
    1-24.JPG
    MMSA[2:0]:PWMA的TRGO输出选择位。
    000:复位。PWMA_EGR寄存器的UG位被用于作为触发输出(TRGO)。
    001:使能。计数器使能信号被用于作为触发输出(TRGO)。其用于启动ADC,以便控制在一段时间内使能ADC。当需要使用PWM触发ADC转换时,需要先设置ADC_CONTR寄存器中的ADC_POWER、ADC_CHS以及ADC_EPWMT,当PWM产生TRGO内部信号时,系统会自动 设置ADC_START来启动AD转换。
    010:更新。更新事件被选为触发输出(TRGO)。
    011:比较脉冲。一旦发生一次捕获或一次比较成功,当CC1IF标志被置1时,触发输出送出一个正脉冲(TRGO)。
    100:比较。OC1REF信号被用于作为触发输出(TRGO)。
    101:比较。OC2REF信号被用于作为触发输出(TRGO)。
    110:比较。OC3REF信号被用于作为触发输出(TRGO)。
    111:比较。OC4REF信号被用于作为触发输出(TRGO)。

    MMSB[2:0]:PWMB的TRGO输出选择位。
    000:复位。PWMB_EGR寄存器的UG位被用于作为触发输出(TRGO)。
    001:使能。计数器使能信号被用于作为触发输出(TRGO)。其用于启动多个PWM,以便控制在一段时间内使能从PWM。
    010:更新。更新事件被选为触发输出(TRGO)。
    (1)只有PWMA的TRGO可用于触发启动ADC。
    (2)只有PWMB的TRGO可用于PWMA的ITR2。
    011:比较脉冲。一旦发生一次捕获或一次比较成功,当CC5IF标志被置1时,触发输出送出一个正脉冲(TRGO)。
    100:比较。OC5REF信号被用于作为触发输出(TRGO)。
    101:比较。OC6REF信号被用于作为触发输出(TRGO)。
    110:比较。OC7REF信号被用于作为触发输出(TRGO)。
    111:比较。OC8REF信号被用于作为触发输出(TRGO)。

    3、控制寄存器2(PWMx_CR2)
    1-25.JPG
    COMSn:捕获/比较控制位的更新控制选择。
    0:当CCPCn=1时,只有在COMG位置1的时候这些控制位才被更新。
    1:当CCPCn=1时,只有在COMG位置1或TRGI发生上升沿的时候这些控制位才被更新。
    COMGn(捕获/比较事件)位在事件产生寄存器(PWMx_EGR)中

    3、控制寄存器2(PWMx_CR2)
    1-26.JPG
    CCPCn:捕获/比较预装载控制位。
    0:CCIE,CCINE,CCiP,CCiNP和OCIM位不是预装载的。
    1:CCIE,CCINE,CCiP,CCiNP和OCIM位是预装载的;设置该位后, 它们只在设置了COMG位后被更新。
    注:该位只对具有互补输出的通道起作用。

    4、从模式控制寄存器(PWMx_SMCR)
    1-27.JPG
    TSA[2:0]:PWMA触发源选择位。
    000:无效;         
    001:无效。
    010:内部触发ITR2。
    011:无效。
    100:TI1的边沿检测器(TI1F_ED)。
    101:滤波后的定时器输入1(TI1FP1)。
    110:滤波后的定时器输入2(TI2FP2)。
    111:外部触发输入(ETRF)。

    TSB[2:0]:PWMB触发源选择位。
    000:无效;
    001:无效;
    010:无效;
    011:无效。
    100:TI5的边沿检测器(TI5F_ED)。
    101:滤波后的定时器输入1(TI5FP5)。
    110:滤波后的定时器输入2(TI5FP6)。
    111:外部触发输入(ETRF)。

    4、从模式控制寄存器(PWMx_SMCR)
    1-28.JPG
    SMSA[2:0]:PWMA时钟/触发/从模式选择位。
    000:内部时钟模式。如果CEN=1,则预分频器直接由内部时钟驱动。
    001:编码器模式1。根据TI1FP1的电平,计数器在TI2FP2的边沿向上/下计数。
    010:编码器模式2。根据TI2FP2的电平,计数器在TI1FP1的边沿向上/下计数。
    011:编码器模式3。根据另一个输入的电平,计数器在TI1FP1和TI2FP2的边沿向上/下计数。100:复位模式。在选中的触发输入(TRGI)的上升沿时重新初始化计数器,并且产生一个更新寄存器的信号。
    101:门控模式。当触发输入(TRGI)为高时,计数器的时钟开启。一旦触发输入变为低,则计数器停止(但不复位)。计数器的启动和停止都是受控的。
    110:触发模式。计数器在触发输入TRGI的上升沿启动(但不复位),只有计数器的启动是受控的。
    111:外部时钟模式1。选中的触发输入(TRGI)的上升沿驱动计数器。

    SMSB[2:0]:PWMB时钟/触发/从模式选择位。
    000:内部时钟模式。如果CEN=1,则预分频器直接由内部时钟驱动。
    001:编码器模式1。根据TI5FP5的电平,计数器在TI6FP6的边沿向上/下计数。
    010:编码器模式2。根据TI6FP6的电平,计数器在TI5FP5的边沿向上/下计数。
    011:编码器模式3。根据另一个输入的电平,计数器在TI5FP5和TI6FP6的边沿向上/下计数。100:复位模式。在选中的触发输入(TRGI)的上升沿时重新初始化计数器,并且产生一个更新寄存器的信号。
    101:门控模式。当触发输入(TRGI)为高时,计数器的时钟开启。一旦触发输入变为低,则计数器停止(但不复位)。计数器的启动和停止都是受控的。
    110:触发模式。计数器在触发输入TRGI的上升沿启动(但不复位),只有计数器的启动是受控的。
    111:外部时钟模式1。选中的触发输入(TRGI)的上升沿驱动计数器。

    1-29.JPG
    ETPn:外部触发ETR的极性控制位。
    0:高电平或上升沿有效;                1:低电平或下降沿有效。
    ECEn:外部时钟使能位。
    0:禁止外部时钟模式2;     1:使能外部时钟模式2,计数器的时钟为ETRF的有效沿。

    5、外部触发寄存器(PWMx_ETR)
    1-30.JPG
    ETFn[3:0]:外部触发滤波器选择,该位域定义了ETRP的采样频率及数字滤波器长度。

    0000:1个时钟;0001:2个时钟;0010:4个时钟;0011:8个时钟;0100:12个时钟;0101:16个时钟;0110:24个时钟;0111:32个时钟;1000:48个时钟;1001:64个时钟;1010:80个时钟;1011:96个时钟;1100:128个时钟;1101:160个时钟;1110:192个时钟;1111:256个时钟。

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-15 19:11:17 | 显示全部楼层
    9月15日,何老师讲述:

    内嵌汇编程序
    嵌入汇编代码的方法
    无论创建.SRC的原因是什么,所需要的步骤始终相同:
    创建C源文件
    添加任何要求的内联汇编指令
    使用SRC命令编译 □
    重命名.SRC文件,这样不会被原始C源文件的后续编译覆盖(如果需要)
    对创建的汇编程序源文件进行修改
    使用汇编器进行汇编
    注:当使用SRC命令时,编译器输出汇编器源文件.SRC,不输出目标(.OBJ)文件。一旦C源文件转换为汇编器源文件,C符号和源代码级调试就不可用
    程序开发人员在使用C语言编写应用程序代码时,经常会遇到需要使用汇编语言编写部分代码的情况
    有些汇编程序在整个软件设计工程中是必须的
    比如:启动引导代码
    而其他地方使用汇编语言是为了提高整个软件设计工程的运行效
    —嵌入汇编代码的方法
    在C语言中使用汇编语言的方法包括两种:
    在C语言程序代码中内嵌汇编语言
    C语言代码程序,调用外部汇编语言编写的程序在C源文件中,将汇编代码写在命令中间
    #pragma asm
             ……….
    #pragmaendasm
    无论创建.SRC的原因是什么,所需要的步骤始终相同:
    创建C源文件
    添加任何要求的内联汇编指令-
    使用SRC命令编译 -
    重命名.SRC文件,这样不会被原始C源文件的后续编译覆盖(如果需要)-
    对创建的汇编程序源文件进行修改
    使用汇编器进行汇编
    注:当使用SRC命令时,编译器输出汇编器源文件.SRC,不输出目标(.OBJ)文件。一旦C源文件转换为汇编器源文件,C符号和源代码级调试就不可用
    内嵌汇编程序-设计实例
    #include "stdio.h"                                        //包含头文件stdio.h
    #include"reg251s.h"                               //包含头文件reg251s.h
    /***** 声明整型变量C1,位于单片机地址为e:0x0100的存储单元****/
    unsigned int edata C1_at_0x100;
    /*****声明整型变量B1,位于单片机地址为e:0x0102的地址单元****/
    unsigned intedata B1 _at_0x102;
    /*****声明整型变量D,位于单片机地址为e:0x0200的地址单元****/
    unsigned intedata D1_at_0x200;
    /***** 声明整型变量e,位于单片机地址为e:0x0202的地址单元*****/
    unsigned int edata e _at_0x202;
    定制文件---基本I/O
    下面的文件包含低层流I/O程序
    使用μVisionIDE时,只需要将修改后的版本添加到工程中即可C
    1-1.JPG
    定制文件---存储器分配
    下面文件用于存储器分配例程的源代码
    1-2.JPG
    存储器分配----calloc
    该函数为具有num元素的数组分配存储器,数组中的每个元素占用len字节并初始化为0。分配的存储器字节总数为num*len
    该函数的原型为:
    #include<stdlib.h>
    *calloc (num, len);
    其中
    num为条目的个数,len为每个条目的长度
    该函数返回一个执行已分配存储器的指针
    如果无法满足存储器分配请求,则返回一个空指针
    存储器分配---free
    free函数将存储块返回到存储池中。参数p指向先前用calloc、malloc或realloc函数分配的存储器块
    该函数的原型为:
    #include<stdlib.h>
    void free(void xdata *p);
    其中
    *p指向要释放的块
    一旦该函数将其返回到存储器池,该块就可以用于后续分配
    如果p是空指针,则忽略它
    存储器分配---init_mempool
    Init_mempool函数初始化存储器管理例程,并且提供存储池的起始地址和大小
    该函数的原型为:
    #include <stdlib.h>
    void init_mempool (void xdata *p, unsigned int size);
    其中
    p参数指向xdata中使用calloc、free、malloc和realloc库函数管理的存 储区域
    size参数指定用于存储池的字节数
    存储器分配----init_mempool
    注:在调用任何其他存储管理函数(calloc、free、malloc、realloc)之前, 程序必须调用init_mempool函数来初始化存储器管理例程,并提供存储池的起始地址和大小。在程序开始时,只调用一次init_mempol函数
    存储器分配---malloc
    该函数从长度为size大小的存储池中分配存储块
    该函数的原型为:
    #include <stdlib.h>
    void xdata *malloc (unsigned int size);
    其中
    size为要分配块的大小
    存储器分配-----realloc
    realloc函数更改之前分配的存储块的大小
    该函数的原型为:
    #include <stdlib.h>
    void xdata *realloc (void xdata *p, unsigned intsize);
    其中:
    p参数指向分配的块,size指定块的新的大小
    现有块的内容将复制到新的块
    由于块大小较大,新块中的任何其他区域都不会初始化
    该函数返回指向新块的指针
    如果存储池中没有足够的存储器来满足存储器请求,则返回空指针,最初的存储块不受影响
    存储器分配---设计实例
    存储器动态分配的C语言描述
    #include"stdlib.h"                          //包含头文件stdlib.h
    /* 声明全局字符数组malloc_mempool*/
    unsigned charxdata malloc_mempool[0x1000];
    void main()                                     //定义main主函数
    {
    int i;                                                      //定义整型变量i
    void *p;                                            //定义指针*p
    /*调用函数init_mempool,初始存储池*/
    init_mempool(&malloc_mempool,sizeof(malloc_mempool));
    存储器分配--设计实例
    p = malloc(100);                                         //调用函数malloc,动态分配存储块
    for(i=0;i<100;i++)                                  //p指向存储块,给存储块的单元分配数
    ((char*)p) = i;                                          //总计执行100次写存储单元的操作
    free(p);                                                       //调用函数free,回收之前分配的存储块
    while(1);                                                        //无限循环设置断点
    }
    C语言设计实例------按键扫描与显示
    本节将使用C语言编写代码,识别STC32G系列单片机硬件开发平台上的按键,并在七段数码管上以从左到右的形式,记录按键的顺序
    比如,第一次按键“1”时,在七段数码管上显示1;在第二次按键“2”时,在七段数码管上显示12;在第三次按键“4”时,在七段数码管上显示124
    由于STC系列单片机硬件开发平台上最多有8个七段数码管,因此可以最多显示当前按键以前8次的按键,按键以其所对应的数字标识
    按键的识别原理
    在STC32系列单片机硬件开发平台上提供了8个按键,这8个按键按2x4形式排列(2行和4列)
    1-3.JPG
    在上电复位后,除P3.0和P3.1引脚外,其他所有I/O引脚均设置为高阻模式
    因此,在上电复位后,需要使用软件正确设置I/O引脚的驱动模반
    当某个I/O引脚Px.y设置为准双向时,如果要读取该引脚的外部输入状态,需要先给引脚Px.y设置为逻辑“1”,然后才能回读该引脚的状态,为什么?要特别注意!!!!!
    七段数码管的原理
    STC32G系列单片机硬件开发平台上的七段数码管驱动电路
    1-4.JPG
    在该硬件开发平台上,通过两个4位七段数码管拼接成一个8位七段数码管
    这8位七段数码管共用a、b、c、d、e、f、g和h段,这8个段通过限流电阻分别连接到STC32G12K128单片机的引脚P6.0~引脚P6.7
    用于选择8位7段数码管的其中一位数码管的信号是COM0~COM7(即管选信号),而COM0~COM7又是由PNP型三极管SS8550驱动。当SS8550的基级为逻辑“0”(低电平)时,三极管导通,8个三极管SS8550的基级通过限流电阻分别连接到STC32G12K128单片机的引脚P7.0~引脚P7.7。当三极管导通时,迅速进入饱和状态,数码管的管选信号COMx为逻辑“1”(高电平)
    —设计中使用的寄存器
    在该设计中,使用了端口PO、P6和P7,对于这3个端口的驱动和控制,需要使用端口模式寄存器和数据寄存器对于端口P6,
    --端口模式寄存器
    PO端口模式寄存器POMO
    该寄存器位于SFR地址为0x94的位置。当复位后,该寄存器的
    内容为“00000000"
    1-5.JPG
    PO端口模式寄存器P0M1
    该寄存器位于SFR地址为0x93的位置。当复位后,该寄存器的内容为“11111111”
    1-6.JPG

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-18 19:28:47 | 显示全部楼层
    9月18日,陈老师讲述:

    STC8H8K64U单片机PWM模块的应用举例—1
    1、PWM输出模式的应用步骤
    (1)设置与PWM复用的IO口的工作模式。(设置PiM1、PiM0寄存器,若电路设计中设置了上拉电阻,可设置为漏极开路模式)
    (2)通道输出脚选择。(设置PWMx_PS寄存器)
    (3)关闭通道。(设置PWMx_CCER1和PWMx_CCER2寄存器,清零其中的 CCxE位。要设置PWM的相关参数,必须先关闭通道)
    (4)配置通道模式。(设置PWMx_CCMR1、PWMx_CCMR2、 PWMx_CCMR3和PWMx_CCMR4寄存器)
    (5)配置通道输出使能和极性。(设置PWMx_CCER1和PWMx_CCER2寄存器)
    (6)设置周期时间。(设置PWMx_ARRH和PWMx_ARRL寄存器)

    1、PWM输出模式的应用步骤
    (7)使能输出。(设置PWMx_ENO寄存器)
    (8)使能主输出。(设置PWMx_BKR寄存器中的MOEx位=1)
    (9)启动PWM计时器。(设置PWMx_CR1寄存器中的CENx=1)
    (10)根据需要调整PWMx_CCR寄存器的值便可以修改PWM输出的占空比。
    1-1.JPG
    2、PWM输出模式的应用举例
    (1)利用PWM1P的输出控制连接的LED灯,      
    P4.0控制给发光二极管上电。
    PWM1P与P6.0复用。
    LED13 每隔1ms更新PWM的占空比。
    核心代码
    P_SW2|=0x80;//扩展寄存器(XFR)访问使能
    1-2.JPG
    P4M1=0x0;P4M0=0x0;      //设置P4口为准双向口
    P6M1=0xff;P6M0=0xff;      //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    PnM1.x          PnMO.x                                                    I/O口模式
    0                       0                                      准双向口
    0                  1                                     推挽输出(强上拉输出,可达20mA,要加限流电阻)
    1                   0                                      仅为输入(高阻)
    1                      1                                         开漏(Open Drain)
    PWMA_PS=0x02;                            //高级PWM通道输出脚选择位
    1-3.JPG
    高级PWM通道1的输出脚可以在三个地方切换,由C1PS[1:0]选择:
    00:PWM1P在P1.0/PWM1P,PWM1N在P1.1/PWM1N;
    01:PWM1P在P2.0/PWM1P_2,PWM1N在P2.1/PWM1N_2;
    10:PWM1P在P6.0/PWM1P_3,PWM1N在P6.1/PWM1N_3。
    PWMA_CCER1=0x00;      //写CCMRx 前必须先清零CCxE关闭通道
    PWMA_CCMR1=0x68;      //通道模式配置
    1-4.JPG
    OC1CE:输出比较1清零使能。该位用于使能使用PWMETI引脚上的外部事件来清通道1的输出信号(OC1REF)。
    0:OC1REF不受ETRF输入的影响;
    OCnM[2:0]:输出比较n模式。
    110:PWM模式1。
    在向上计数时,当PWMn_CNT<PWMn_CCR1时,OCnREF输出高,否则OCnREF输出低; 在向下计数时,当PWMn_CNT>PWMn_CCR1时,OCnREF输出低,否则OCnREF输出高。
    PWMA_CCER1=0x00;    //写CCMRx前必须先清零CCxE关闭通道
    PWMA_CCMR1=0x68;     //通道模式配置
    1-5.JPG
    CC1S[1:0]OCnPE:输出比较n预装载使能(n=1,5)。
    1:开启PWMn_CCR1寄存器的预装载功能,读写操作仅对预装载寄存器操作,PWMn_CCR1的预装载值在更新事件到来时被加载至当前寄存器中。
    OC1FE:输出比较1快速使能。
    0:根据计数器与CCR1的值,CC1正常操作。
    CC1S[1:0]:捕获/比较1选择。定义通道的方向(输入/输出),及输入脚的选择。
    00:输出。
    PWMA_CCER1=0x00;   //写CCMRx前必须先清零CCxE关闭通道
    PWMA_CCMR1=0x68;    //通道模式配置
    1-6.JPG
    CC1S[1:0]OCnPE:输出比较n预装载使能(n=1,5)。
    1:开启PWMn_CCR1寄存器的预装载功能,读写操作仅对预装载寄存器操作,PWMn_CCR1的预装载值在更新事件到来时被加载至当前寄存器中。
    OC1FE:输出比较1快速使能。
    0:根据计数器与CCR1的值,CC1正常操作。
    CC1S[1:0]:捕获/比较1选择。定义通道的方向(输入/输出),及输入脚的选择。
    00:输出。
    PWMA_CCER1=0x01;     //配置通道输出使能和极性
    1-7.JPG
    CC1P:OC1输入捕获/比较输出极性。
    CC1通道配置为输出时:  
    0:高电平有效;                                                  1:低电平有效。
    CC1通道配置为输入或者捕获:
    0:捕获发生在TI1F或TI2F的上升沿;         1:捕获发生在TI1F或TI2F的下降沿。
    CC1E:OC1输入捕获/比较输出使能。
    0:关闭输入捕获/比较输出;                                1:开启输入捕获/比较输出。
    PWMA_ARRH= (u8)(PWM_PERIOD>>8);//设置周期时间
    PWMA_ARRL=(u8)PWM_PERIOD;
    1-8.JPG
    PWMA_ENO=0x01;                          //使能输出
    1-9.JPG
    ENO1P ENO1P:PWM1P输出控制位。
    0:禁止PWM1P输出;1:使能PWM1P输出。
    PWMA_BKR=0x80;          //使能主输出
    1-10.JPG
    MOEn:主输出使能。一旦刹车输入有效,该位被硬件异步清0。根据AOE位的设置值,该位可以由软件置1或被自动置1。它仅对配置为输出的通道有效。
    (n=A,B,下同)
    0:禁止OC和OCN输出或强制为空闲状态
    1:如果设置了相应的使能位(PWMn_CCERx寄存器的CCIE位),则使能OCn和OCnN输出。
    PWMA_CR1=0x01;//开始计时
    1-11.JPG
    CENn:允许计数器控制位。
    0:禁止计数器;                             1:使能计数器。
    PWMA_CCR1H=(u8)(PWM1_Duty>>8);//设置占空比时间 PWMA_CCR1L=(u8)(PWM1_Duty);
    1-12.JPG
    2、PWM输出模式的应用举例
    1-13.JPG

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-19 19:47:34 | 显示全部楼层
    9月19日,何宾老师讲述:

    主要内容:
    时钟子系统
    复位子系统
    电源子系统
    设计实例一:软件复位的实现设计
    实例二:看门狗定时器的应用
    设计实例三:进入和退出空闲模式的实现
    设计实例四:进入和退出掉电模式的实现
    时钟子系统
    在STC32G系列单片机内提供了系统时钟控制器,该控制
    器为单片机内的CPU和所有外设提供时钟源
    根据产生时钟的功能,将该系统时钟控制器划分为三级结构
    1-1.JPG
    时钟子系统--第一级时钟
    在STC32G系列单片机中,第一级时钟为时钟源,产生不同频率的时钟
    在HIRCCR寄存器ENHIRC字段(HIRCCR.ENHIRC)的控制下, 内部高速IRC可以产生4个不同频率的时钟信号
    包括6MHz、10MHz、27MHz和44MHz。这四个时钟频率信号同时送到由IRCBAND寄存器SEL字段(IRCBAND.SEL)控制的多路选择器 mux1,多路选择器mux1最终输出时钟信号HIRC
    在XOSCCR寄存器ENXOSC字段(XOSCCR.ENCOSC)的控 制下,将外部晶体振荡器产生的时钟信号XOSC馈入到STC32G系列单片机的内部
    相关的寄存器列表
    --IRC频段选择寄存器(IRCBAND) 寄存器IRCBAND位于SFR地址为0xA9的位置
    1-2.JPG
    USBCKS/USBCKS2:USB时钟选择寄存器
    1-3.JPG
    SEL[1:0]:频率选择字段

    4

    4

    相关的寄存器列表--USB时钟控制寄存器(USBCLK)
    寄存器USBCLK位于SFR地址为0xDC的位置
    1-5.JPG
    ENCKM:PLL倍频控制位。当该位为“0”时,禁止PLL;当该位为“1”时,使能PLL
    PCKI[1:0]:PLL时钟选择位。
    CRE:时钟追频控制位。当该位为“0”时,禁止时钟跟踪频率;当该位为“1”时,使能时钟跟踪频率
    相关的寄存器列表—系统时钟选择寄存器(CLKSEL)
    寄存器CLKSEL位于XSFR地址为0x7EFE00的位置 位
    1-6.JPG
    CKMS:内部PLL输出时钟选择位。当该位为“0”时,PLL输出96MHz;当该位为“1”时,PLL输出144MHz
    HSIOCK:高速I/O时钟源选择位。当该位为“0”时,主时钟MCLK为高速I/O时钟源;当该位为“1”时,PLL输出96MHz/144MHz的PLLCLK 为高速I/O时钟源
    MCK2SEL[1:0]:主时钟源选择位
    1-7.JPG
    MCKSEL[1:0]:主时钟源选择位。
    相关的寄存器列表—时钟分频寄存器(CLKDIV)
    寄存器CLKDIV位于XSFR地址为0x7EFE01的位置

    8

    8

    CLKDIV为主时钟分频系数(范围1~255)。系统时钟SYSCLK是对主时钟MCLK进行分频后的时钟信号
    时钟MCLK与系统时钟之间的关系为
    fsYscLk=fMcLK/DIV[7:0]
    当DIV[7:0]=0时,fsyscLk=fMcLK
    相关的寄存器列表—内部高速高精度IRC控制寄存器(HIRCCR)
    寄存器HIRCCR位于XSFR地址为0x7EFE02的位置
    1-9.JPG
    ENHIRC:内部高速高精度IRC使能位。当该位为“0”时,关闭内部高精度IRC。当该位为“1”时,使能内部高精度IRC
    HIRCST:内部高速高精度IRC频率稳定标志位(只读).当内部的IRC从停振状态开始使能后,必须经过一段时间,振荡器才能稳定。当稳定后,时钟控制器会自动将HIRCST标志位设置为“1”。当用户程序需要将时钟切换到使用内部IRC时,首先必须将ENHIRC设置为“1”以使能振荡器然后轮询振荡器稳定标志位HIRCST,直到该标志位变为“1”时,才能切换时钟源
    相关的寄存器列表——外部振荡器控制寄存器(XOSCCR)
    寄存器XOSCCR位于XSFR地址为0x7EFE03的位置
    1-10.JPG
    ENXOSC:外部晶体振荡器使能位。当该位为“0”时,关闭外部晶体振荡器。当该位为“1”时,使能外部晶体振荡器
    XITYPE:外部时钟源类型选择位。当该位为“0”时,外部时钟源是外部时钟信号(或有源晶振)。信号源只需连接单片机的XTALI(P1.7);当该位为“1”时,外部时钟源是晶体振荡器。信号源连接单片机的XTALI(P1.7)和XTALO (P1.6)
    相关的寄存器列表——外部振荡器控制寄存器(XOSCCR)
    XCFILTER[1:0]:外部晶体振荡器抗干扰控制寄存器
    1-11.JPG
    GAIN:外部晶体振荡器振荡增益控制位,当该位为“0“时,关闭振荡增益(低增益);当该位为”1“时,使能振荡增益(高增益)
    XOSCST:外部晶体振荡器频率稳定标志位(只读)。当外部晶体振荡器从停振状态开始使能后,必须经过一段时间,振荡器才能稳定。当稳定后时钟控制器会自动将XOSCST标志位设置为“1”。当用户程序需要将时钟切换到使用外部晶体振荡器时,首先将ENXOSC设置为”1”以使能振荡器,然后轮询振荡器稳定标志位XOSCST,直到该标志变为“1”时,才可以切换时钟源
    相关的寄存器列表--内部32KHz低速IRC控制寄存器(IRC32KCR)
    寄存器IRC32KCR位于XSFR地址为0x7EFE04的位置

    12

    12

    ENIRC32K:内部32K低速IRC使能位。当该位为“0”时,关闭内部32K低速IRC;当该位为“1”时,使能内部32K低速IRC
    IRC32KST:内部32K低速IRC频率稳定标志位(只读)。当内部32K低速IRC从停振状态开始使能后,必须经过一段时间,振荡器才能稳定。当稳定后,时钟控制器会自动将IRC32KST标志位设置为“1”。当用户程序需要将时钟切换到使用内部32K低速IRC时,首先必须将ENIRC32K设置为“1”以使能振荡器,然后轮询振荡器稳定标志位IRC32KST,直到标志位变为“1”时,才可切换时钟源
    相关的寄存器列表-----主时钟输出控制寄存器(MCLKOCR)
    寄存器MCLKOCR位于XSFR地址为0x7EFE05的位置
    1-13.JPG
    MCLKO_S:系统时钟输出管脚选择位。当该位为“0”时,从P5.4引脚输出系统时钟分频后的时钟;当该位为“1”时,从P1.6引脚输出系统时钟分频后的时钟
    MCLKODIV:对系统时钟的分频由MCLKODIV[6:0]确定,即fsvsclk/ MCLKODIV[6:0]。当MCLKODIV[6:0]=" 0000000”时,不输出分频 后的时钟
    相关的寄存器列表----主时钟输出控制寄存器(MCLKOCR)
    寄存器MCLKOCR位于XSFR地址为0x7EFE05的位置
    1-14.JPG MCLKO_S:系统时钟输出管脚选择位。当该位为“0”时,从P5.4引脚输出系统时钟分频后的时钟;当该位为“1”时,从P1.6引脚输出系统时钟分频后的时钟
    MCLKODIV:对系统时钟的分频由MCLKODIV[6:0]确定,即fsysclk/ MCLKODIV[6:0]。当MCLKODIV[6:0]="0000000
    时,不输出分频 后的时钟
    相关的寄存器列表—高速振荡器稳定时间控制寄存器(IRCDB)
    寄存器IRCDB位于XSFR地址为0x7EFE06的位置
    1-15.JPG
    IRCDB[7:0]:内部高速振荡器稳定时间控制字段。当该字段值为0时,需要256个时钟,当该字段值不为0时,该字段的值对应于所需要的时钟个数,如当该字段为2时,需要2个时钟
    相关的寄存器列表--内部48MHz高速IRC控制寄存器(IRC48MCR)
    寄存器IRC48MCR位于XSFR地址为0x7EFE07的位置

    16

    16

    ENIRC48M:内部48M高速IRC使能位。当该位为“0”时,关闭内部48MHz高速IRC;当该位为“1”时,使能内部48MHz高速IRC
    IRC48MST:内部48M高速IRC频率稳定标志位(只读)。当内部48M高速IRC从停振状态开始使能后,必须经过一段时间,振荡器才能稳定。当稳定后,时钟控制器会自动将IRC48MST标志设置为“1”。当用户程序需要将时钟切换到使用内部48M高速IRC时,首先必须将ENIRC48M设置为“1”以使能振荡器,然后轮询振荡器稳定标志位IRC48MST,直到标志位变为“1”时,才可切换时钟源
    相关的寄存器列表—外部32K振荡器控制寄存器(X32KCR)
    寄存器X32KCR位于XSFR地址为0x7EFE08的位置
    1-17.JPG
    ENX32K:外部32K晶体振荡器使能位。当该位为“0”时,关闭外部32K晶体振荡器;当该位为”1“时,使能外部32K晶体振荡器
    GAIN32K:外部32K晶体振荡器振荡增益控制位。当该位为“0”时,关闭32K振荡增益(低增益);当该位为“1“时,使能32K振荡增益(高增益)
    X32KST:外部32K晶体振荡器频率稳定标志位(只读)
    相关的寄存器列表----高速时钟分频寄存器(HSCLKDIV)
    寄存器HSCLKDIV位于XSFR地址为0x7EFE0B的位置
    1-18.JPG
    HSCLKDIV[7:0]为高速I/O时钟分频系数值
    fHSCLK和 高速1/o时钟源之间的关系满足
    fHscLк=f高速1/o时钟源/HSCLKDIV[7:0]
    复位子系统--硬件复位
    当硬件复位时,将所有寄存器的值复位到默认的初始值,系统会重新读取所有的硬件选项。同时根据硬件选项所设置的上电等待时间进行上电等待
    硬件复位包括上电复位、低压复位、复位脚复位(低电平有效)和看门狗复位
    硬件复位--掉电/上电复位
    当电源电压VCC低于掉电复位/上电复位检测门限电压时将单片机内的所有电路复位
    该复位属于冷启动复位的一种
    当内部VCC电压高于掉电复位/上电复位检测门限电压后,延迟32768个时钟后结束掉电/上电复位过程
    当该过程结束后,单片机将特殊功能寄存器IAP_CONTR中的
    SWBS/IAP_CONTR.6位置1,同时从系统ISP监控区启动程序
    对于5V供电的单片机来说,它的掉电复位/上电复位检测门限电压为3.2V;对于3.3V供电的单片机来说,它的掉电复位/上电复位检测门限电压为1.8V
    硬件复位-复位引脚复位
    1-19.JPG
    在STC32G系列单片机中,复位引脚设置在P5.4引脚上
    当外部给该引脚施加一定宽度的脉冲后,对单片机进行复位
    复位引脚复位是热启动复位中的硬复位
    当在STC—ISP软件的"硬件选项”
    硬件选项
    标签界面中勾选“复位脚用作I/O
    口”前面的复选框时,引脚是普 通I/O,
    不能用于RST引脚;当不 勾选“复位脚用
    作I/O口“前面的复选框时,P5.4引脚为
    专用的复位引脚
    硬件复位
    ——MAX810专用复位电路复位
    STC32G系列单片机内部集成了MAX810专用复位电路
    当STC—ISP软件的“硬件选项“标签界面中勾选"上电复位使用较长延时”选项前面的复选框时,允许使用STC32G系列单片机内MAX810专用复位电路
    当使能使用该专用复位电路时,在掉电复位/上电复位后产生约180mS复位
    延时,然后才结束复位过程。当该过程结束后,
    单片机将特殊功能寄 存器IAP_CONTR中的SWBS/
    IAP CONTR.6位置1,同时从系统ISP监控区启动程序
    硬件复位----内部低压检测复位
    除了上面提供的上电复位检测门限电压外,STC8系列单片机还额外提供了一组更可靠的内部低电压检测门限电压
    该复位方式属于热启动复位中的一种硬件复位方式
    当电源电压Vcc低于内部低电压检测(Low Voltage Detection, LVD) 门限电压时,可产生复位信号
    在STC—ISP软件的“硬件选项"标签界面中勾选”允许低压复位(禁止低 压中断)”前面的复选框,则使能低压检测

    20

    20

    硬件复位----内部低压检测复位
    若不勾选”允许低压复位(禁止低压中断)”前面的复选框,则使能低电压检测中断
    在STC—ISP软件中,通过低压检测电压右侧的下拉框可以设置低压检测门限,包括2.00V、2.40V、2.70V和3.00V

    21

    21

    硬件复位----内部低压检测复位
    使能低电压检测中断时,当电源电压VCC低于内部低电压检测LVD门限电压时,硬件将中断请求标志位LVDF/PCON.5设置为“1”,并且若ELVD/IE.6(低压检测中断允许位)也设置为“1”,就将向STC32G系列单片机的处理器发出低电压检测中断信号
    当正常工作和处于空闲工作状态时,如果内部工作电压VCC低于低电压检测门限时,将中断请求标志位LVDF/PCON.5自动设置为“1”,与低压检测中断是否被允许无关
    注:该位必须由软件清“0”。在清“0”后,如果内部工作电压VCC继续低于检测门限电压,则将该位再次自动设置为“1”
    硬件复位——内部低压检测复位
    当进入掉电工作状态前,如果低压检测电路未被允许产生中断,则在进入掉电模式后,该低压检测电路不工作以降低功耗。如果允许可产生低压检测中断,则在进入掉电模式后,该低压检测电路将继续工作,在内部工作电压VCC低于低压检测门限电压时,产生低压检测中断,可以将MCU从掉电状态唤醒
    在低压检测复位结束后,不影响特殊功能寄存器IAP_CONTR中的SWBS/IAP_CONTR.6位的值,单片机根据复位前SWBS/IAP_CONTR.6的值选择从用户应用程序区启动,还是从系统监控区启动
    复位子系统-----软件复位
    软件复位时,除与时钟相关的寄存器保持不变外,其余的所有寄存器的值会复位到初始值,软件复位不会重新读取所有的硬件选项
    软件复位包括写IAP_CONTR的SWRST所触发的复位
    相关的寄存器列表—看门狗控制寄存器(WDT_CONTR)
    寄存器WDT_CONTR位于SFR地址为0xC1的位置

    22

    22

    WDT_FLAG:看门狗溢出标志。当看门狗溢出时,硬件自动将该位设置为“1“,需要软件将该位清零
    EN_WDT:看门狗使能位。当该位为“0”时,对单片机无影响;当该位为“1”时,启动看门狗定时器
    CLR_WDT:看门狗定时器清零。当该位为“0”时,对单片机无影响。当该位为“1”时,清零看门狗定时器,硬件自动将该位复位
    IDL_WDT:IDLE模式时的看门狗控制位。当该位为“0”时,IDLE模式时看门狗停止计数;当该位为“1”时,IDLE模式时看门狗继续计数
    相关的寄存器列表—看门狗控制寄存器(WDT_CONTR)
    WDT_PS[2:0]:看门狗定时器时钟分频系数

    23

    23

    相关的寄存器列表-----IAP控制寄存器(IAP_CONTR)
    寄存器IAP_CONTR位于SFR地址为0xC7的位置

    24

    24

    SWBS:软件复位启动选择位。当该位为“0”时,软件复位后从用户程序区开始执行代码。用户数据区的数据保持不变;当该位为“1”时,软件复位后从系统ISP区开始执行代码。用户数据区的数据会被初始化
    SWRST:软件复位触发位。当该位为“0“时,对单片机无影响;当该位为”1“时,触发软件复位
    相关的寄存器列表——复位配置寄存器(RSTCFG)
    寄存器RSTCFG位于SFR地址为0xFF的位置

    25

    25

    ENLVR:低压复位控制位。当该位为“0”时,禁止低压复位。当系统检测到低电压事件时,会产生低压中断。当该位为“1”时,使能低电压复位。当系统检测到低电压事件时,自动复位
    P54RST:RST管脚功能选择位。当该位为“0”时,RST管脚用作普通I/O口(P5.4引脚);当该位为“1”时,RST管脚用作复位脚(低电平有效)
    相关的寄存器列表—复位配置寄存器(RSTCFG)
    LVDS[1:0]:低压检测门槛电压设置字段

    26

    26
    ]
    相关的寄存器列表—复位标志寄存器(RSTFLAG)
    寄存器RSTFLAG位于XSFR地址为0x7EFE99的位置
    1-27.JPG
    LVDRSTF:LVD低压复位标志。当读取该位时,“1”表示当前的复位是由低电压复位所触发;当给该位写“1”时,清除该标志位
    WDTRSTF:看门狗复位标志。当读取该位时,“1”表示当前的复位由看门狗溢出触发;当给该位写“1”时,清除该标志位
    SWRSTF:软复位标志。当读取该位时,“1”表示当前的复位是由软件写SWRST(IAP_CONTR.5)所触发。当给该位写“1”时,清除该标志位
    ROMOVF:代码区溢出标志。当读取该位时,“1”表示当前的复位是由于CPU执行代码到非程序区导致的代码区溢出所触发;当给该位写“1”时,清除该标志位
    相关的寄存器列表——复位控制寄存器(RSTCRx)
    复位控制寄存器RSTCRx(x=0、1、2、3或4)分别位于XSFR地址为0x7EFE9A、0x7EFE9B、0x7EFE9C、0x7EFE9D和 0x7EFE9E的位置,写“1”复位相应的模块,需软件清零
    寄存器RSTCRO的内容

    28

    28

    RSTTM34为定时器3和定时器4模块的复位控制位
    RSTTM2为定时器2模块的复位控制位
    RSTTM1为定时器1模块的复位控制位
    相关的寄存器列表—复位控制寄存器(RSTCRx)
    寄存器RSTCR1的内容

    29

    29

    RSTUART4为UART4模块的复位控制位
    RSTUART3为UART3模块的复位控制位
    RSTUART2为UART2模块的复位控制位
    RSTUART1为UART1模块的复位控制位
    相关的寄存器列表—复位控制寄存器(RSTCRx)
    寄存器RSTCR2的内容

    30

    30

    RSTCAN2为CAN2模块的复位控制位
    RSTCAN为CAN模块的复位控制位-
    RSTLIN为LIN模块的复位控制位
    RSTRTC为RTC模块的复位控制位
    RSTPWMB为PWMB模块的复位控制位
    RSTPWMA为PWMA模块的复位控制位
    RSTI2C为I2C模块的复位控制位
    RSTSPI为SPI模块的复位控制位
    相关的寄存器列表—复位控制寄存器(RSTCRx)
    寄存器RSTCR4的内容

    31

    31

    RSTMDU为MDU模块的复位控制位
    电源子系统----运行模式
    STC32G系列单片机提供了三种降低功耗的运行模式
    低速模式
    空闲模式
    掉电模式
    运行模式-------空闲模式
    将PCON寄存器内的IDL/PCON.0位设置为“1”时,单片机将进入IDLE(空闲)模式
    在空闲模式下,仅CPU无时钟,但是外部中断、内部低压检测电路、定时器、ADC转换器等仍正常工作
    通过寄存器和STC—ISP软件,可以设置在空闲期间看门狗定时器是否继续计数
    在空闲模式下,数据RAM、堆栈指针SP、程序计数器PC、程序状态字PSW、累加器A等寄存器都保持原有的数据
    I/O口保持空闲模式被激活前的逻辑状态
    运行模式------空闲模式
    在空闲模式下,除了STC32G系列单片机内的处理器外,单片机的所有外设都能正常工作
    当产生任何一个中断时,它们均可以唤醒单片机。当唤醒单片机后,CPU继续执行进入空闲模式语句的下一条指令
    运行模式-------掉电模式
    将PCON寄存器的PD位设置为“1”,则STC32G单片机进入掉电模式,也称为停机模式
    进入掉电模式后,单片机所使用的时钟停止振荡,包括内部系统时钟、外部晶体振荡器和外部时钟)
    由于没有时钟振荡,CPU、看门狗、定时器、串行口、ADC等模块停止工作
    外部中断(包括INTO/INT1/INT2/INT3/INT4),以及CCP继续工作
    如果允许低压检测电路产生中断,则低压检测电路可以继续工作;否则,将停止工作
    进入掉电模式后,STC32G系列单片机的所有端口、特殊功能寄存器维持进入掉电模式前一时刻的状态不变
    运行模式------掉电模式
    如果在掉电前,打开掉电唤醒定时器,则进入掉电模式后,掉电唤醒专用定时器将开始工作
    进入掉电模式后,STC32G系列单片机可将掉电模式唤醒的引脚资源有
    INTO/P3.2、INT1/P3.3(INTO/INT1上升沿和下降沿均可产生中断) INT2/P3.6,INT3/P3.7、INT4/P3.0(仅可以下降沿产生中断)、引脚CCPO/CCP1/CCP2、引脚 RxD/RxD2/RxD3/RxD4、引脚 TO/T1/T2/T3/T4(下降沿即外部引脚TO/T1/T2/T3/T4由高到低的变化前提是在进入掉电模式前已经允许相应的定时器中断)、低压检测中断(前提是低压检测中断被允许,且STC—ISP软件中,不勾选“允许低压复位/禁止低压中断”前面的复选框
    相关的寄存器列表——电源控制寄存器(PCON)
    寄存器PCON位于SFR地址为0x87的位置

    32

    32

    LVDF:低压检测标志位。当系统检测到低压事件时,硬件自动将该位设置为“1”,并向CPU提出中断请求。此位需要用户软件清零
    POF:上电标志位。硬件自动将该位设置为“1”
    PD:掉电模式控制位。当该位为“1”时,单片机进入时钟停振模式/掉电模式,处理器以及全部外设均停止工作。唤醒后硬件自动清零
    IDL:IDLE(空闲)模式控制位。当该位为“1”时,单片机进入IDLE模
    式,只有处理器停止工作,其他外设依然在运行。唤醒后硬件自动清零
    注:时钟停振模式下,处理器和全部的外设均停止工作,但SRAM和XRAM中的数据是一直保持不变
    相关的寄存器列表------掉电唤醒定时器(WKTCL和WKTCH)
    内部掉电唤醒定时器是一个15位的计数器(由{WKTCH[6:0],WKTCL[7:0]}组成15位)
    用于唤醒处于掉电模式的MCU
    寄存器WKTCL位于SFR地址为0xAA的位置,寄存器WKTCH位 于SFR地址为0xAB的位置

    33

    33

    WKTEN:掉电唤醒定时器的使能控制位。当该位为“0“时,禁止掉电唤醒定时器;当该位为“1”时,使能掉电唤醒定时器
    相关的寄存器列表--掉电唤醒定时器(WKTCL和WKTCH)

    34

    34


    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    昨天 08:56
  • 签到天数: 43 天

    [LV.5]常住居民I

    6

    主题

    57

    回帖

    500

    积分

    高级会员

    积分
    500
     楼主| 发表于 2023-9-20 18:47:06 | 显示全部楼层
    9月20日,今天由陈老师和STC工程师共同授课,温度控制的实列讲得很透彻,利用试验箱再好好复习,加深理解。
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-6-3 06:32 , Processed in 0.109104 second(s), 66 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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