找回密码
 立即注册
楼主: 大亮

《STC教学研讨会STC8H/STC32G》--学习记录/学习心得--打卡帖 | 建议送

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-19 16:00:47 | 显示全部楼层
本帖最后由 大亮 于 2023-9-19 16:02 编辑

《何教授 STC32位8051单片机原理及应用-STC32G12K128》2023/9/12



截图202309191100206684.jpg --》 截图202309191101038326.jpg --》 截图202309191101545498.jpg 启动引导过程!

截图202309191103518203.jpg == 截图202309191104132444.jpg 立即数送累加器,累加器送edata



截图202309191105438964.jpg 截图202309191106031693.jpg 16位立即数送16位寄存器(选择按寄存器规约),寄存器送0x0009内存地址


截图202309191111091848.jpg 截图202309191111318105.jpg 32位立即数,低地址送高编号16位寄存器 ,高地址送低编号16位寄存器,DR送内存,体现大端模式好处

截图202309191128449648.jpg 搬移

截图202309191130026673.jpg 搬移 符号扩展

截图202309191132006535.jpg 截图202309191133035673.jpg 截图202309191135526619.jpg


数组:
截图202309191148269314.jpg 数组在edata中的地址,code中的调用操作edata地址及内容


可重入行数/递归函数的C语言描述

调用堆栈!   地址在什么地方,当前y值是多少
截图202309191431446946.jpg FIB入栈了 截图202309191433117665.jpg 截图202309191434492793.jpg


函数,存储器模型    规约限制
截图202309191438272828.jpg 《寄存器使用规约》 int类型的时候   2字节ptr 分配顺序 WR6 WR4 WR2 WR0   寄存器不够了,先移放到0x08 0x0a edata  small

截图202309191444004384.jpg 截图202309191445222080.jpg LARGE  WR6 WR4 WR2 WR0   寄存器不够了 放Xdata   !!!!!!!


函数指针!!
截图202309191451134726.jpg edata里的指针变量指向code里的程序入口地址,操作P,操作不同子程序


截图202309191455099653.jpg 截图202309191458082399.jpg        函数指针,对于底层 , 间接寻址!

属性!  __attribute__

截图202309191508149002.jpg 截图202309191509542515.jpg   映射 别名 隐藏信息


__aligned()__
截图202309191515077292.jpg    对齐     分配存储空间的位置 截图202309191525251786.jpg
   

noreturn

预处理器  编译器执行的第一个操作,插入或替换额外的文本到原文件里去
#include   头文件的多次包含,编译器报错! 解决 条件包含头文件     条件编译!

宏:源代码块指定名字     只会减少代码的书写,不会减少编译后的代码

#define LEN 128     //程序的修改行,适应性,可移植性
复杂的宏  预处理器有计算能力  勤用()保障优先级和结合性

C99标准 可变参数宏  字符串化操作符#   标记粘贴操作符##  定义的操作符

预定义的宏  C251编译器提供了一下预定义的宏: 。。。。。
截图202309191555251824.jpg

截图202309191557187388.jpg

预处理器~
截图202309191559275836.jpg 截图202309191559573573.jpg 截图202309191600283083.jpg


截图202309191457052453.jpg
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-20 04:44:15 | 显示全部楼层
《何教授 STC32位8051单片机原理及应用-STC32G12K128》2023/9/15



周五上午9:00~12:00

=====================================================================================


单片机基础设计硬件知识


=====================================================================================


内嵌汇编语言: 程序远在使用C语言编写应用程序代码时,经常会遇到需要使用汇编语言编写部分代码的情况        启动引导代码必须汇编程序,提高工程的运行效率


C语言中使用汇编:代码中嵌入汇编语言  调用外部汇编文件或程序

#progma asm
   ........ ........ ........
#progma endasm

使用上两命令将内联汇编添加到C函数中
需要手工优化编译器的汇编程序输出
C语言原型化函数和参数
使用汇编器进行汇编

截图202309192029021877.jpg 截图202309192031315579.jpg 截图202309192137172051.jpg 某种意义上的图形化操作,代替Linux敲指令模式


C语言生成的数据放寄存器,汇编操作寄存器实现目的

定制文件:
基本IO         串口重定位技术         串口协议    PUTCHAR.C      GETKEY.C
存储器分配      提供动态管理各逻辑区域          CALLOC.C      FREE.C      INIT_MEM.C      MALLOC.C      REALLOC.C     库函数   复杂操作系统中应用特别多

#include <stdlib.h>
*calloc(num,len);
void free(void xdata *p); //存储器泄露问题
void init_mempool(void xdata *p, unsigned int size);  //在调用任何其他存储管理函数(calloc free malloc realloc)之前,程序必须调用init_mempool函数来初始化存储器管理例程,并提供存储池的起始位置和大小,在程序开始前,只调用一次init_mempool函数。
void xdata *malloc(unsigned int size);  

void xdata*realloc(unsigned int size);
截图202309200336085980.jpg 截图202309200338297173.jpg

动态分配

综合设计实例

分析电路
截图202309200355036438.jpg 在上电复位后,除P3.0P3.1引脚外,其他所有IO引脚均初始化为高阻状态, 当某个IO一脚设置为准双向时,如果要读取该引脚的外部输入状态,需要先给引脚设置为逻辑1,经过一个延时,才能回读该引脚的状态。


我们的工作:实现软件和硬件协同  协同设计、系统仿真、协同调试     FPGA硬件思维  

使用的寄存器:模式寄存器(PxM1,PxM0)和数据寄存器(Px.n)

数据寄存器,当给对应的位写“0”时,输出逻辑“0”(低电平)到端口对应引脚(Px.n)的缓冲区;
                    当给对应的位写“1”时,输出逻辑“1”(高电平)到端口对应引脚(Px.n)的缓冲区;
                   当读取该寄存器时,直接读取端口对应引脚(Px.n)上的电平

代码review

#ifndef  STC32G12K128_SYMBOL
#define  STC32G12K128_SYMBOL

sfr P6    =  0xE8;
sfr P7    =  0xF8;
sfr P0M0  =  0x94;
sfr P0M1  =  0x93;
sfr P6M0  =  0xCC;
sfr P6M1  =  0xCB;
sfr P7M0  =  0xE2;
sfr P7M1  =  0xE1;//写头文件,定义SFR,用条件编译的方式避免包含
#endif



#include "reg251s.h"
#include "configure.h"//预处理使用库函数



void IO_KeyDelay(void)                     //延时函数 设计单片机时钟主频等知识,9月19日课程重点讲授
{
        unsigned char i;
        i = 60;
        while(--i)        ;
}


void main(){
        char i=0;
        int j=0;
        char seg[8]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};   // 段码
        char key_record[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
        unsigned char c1_new,c1_old=0,c1;        //处理扫描中按键常闭
        P0M0=0;
        P0M1=0;
        P6M0=0;
        P6M1=0;
        P7M0=0;
        P7M1=0;
        P7=0xff;}

while(1){ } //main body 按键扫描  驱动数码管。。。。。。


====================================================================
后面课程: 电源管理和时钟复位
                定时器和计时器
                串口原理和应用和串口重定位
                ADC
                PWM 和 PWM两个典型应用
                DMA
                USB原理和应用



回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-20 10:25:10 | 显示全部楼层
本帖最后由 大亮 于 2023-9-20 11:28 编辑

《陈教授 1T 8051 单片机原理及应用-STC8H8K64U 》-2023/9/13



结构图 截图202309200803592941.jpg
基时单元的预分频时钟(CK_PSC):内部时钟(CK_INT)/外部时钟模式1外部时钟输入(TIx)/外部时钟模式2:外部触发输入ETR/ 内部触发输入(ITRx)

内部时钟: 主时钟--》 定时器时钟 --》 计数器寄存器--> UG --> 清零

外部时钟源模式1: TI2 --》 滤波器  --》边缘检测  --》 输入带宽选择 --》 极性--》 配置输入源--》启动

外部时钟源模式2: ETR信号的每一个上升沿或者下降沿计数

截图202309200858017693.jpg 所有信号都与主时钟对齐


捕获/比较 通道:P端作为捕获通道

输出模式:输出控制


寄存器:输出使能寄存器(PWMX_ENO)   控制寄存器x(PWMx_CR1)    控制寄存器2(PWMx_CR2)    从模式控制寄存器(PWMx_SMCR) 外部触发寄存器(PWMx_ETR)中断使能寄存器(PWMx_IER) 状态寄存器1(PWMx_SR1) 状态寄存器2(PWMx_SR2)      事件产生寄存器(PWMx_EGR)   捕获比较模式寄存器x(PWMx_CCMR1) 捕获比较使能寄存器x(PWMx_CCER1)
计数器高8位 计数器低8位 预分频寄存器高8位 预分频寄存器低8位  自动重装载寄存器 重复计数器 捕获比较寄存器数据  刹车寄存器

PWM(一个周期、一个占空比)做电机控制、做功放、做逆变器 、DA 等实用项目比较复杂
COM事件(准备好下一个环境的时间,中断来了一起生效): HALL信号指示COM事件进行无刷电机换相,6路PWM同时对应    六步顺序换相 给MOSFET一点死区时间   同时更新6路PWM状态
截图202309201126403238.jpg 截图202309201114489403.jpg

高电平时间很短,0.5um MCU忙不过来:上升沿高电平硬件级锁存起来,   中断当前程序运行,     断点保护入栈,    长跳转到中断入口地址,   处理中断服务,    中断恢复, 退出中断
最小脉宽要求(高/低电平的最小时间)
8H系列高级功能: 高级PWM   单个捕捉同PCA   IC1和IC2一起映射到TI1(两路捕捉,上升沿、下降沿都捕捉),高电平时间可以很短,一个周期中断两次。对应低电平时间短极限情况,复位PWMA_ARR计数器

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-20 16:29:42 | 显示全部楼层
《陈教授 1T 8051 单片机原理及应用-STC8H8K64U 》-2023/9/18 -Mon -PWM Enhance



PWM模块的应用:输出PWM,输入测量

PWM输出模式的应用步骤:
1、设置PWM复用的IO口的工作模式,开漏 PIM1,PIMO
2、通道输出脚选择 PWMx_PS
3、关闭通道 PWMX_CCER1 PWMX_CCER2
4、配置通道模式 PWMX_CCMR1 PWMX_CCMR2 PWMX_CCMR3 PWMX_CCMR4
5、配置通道输出使能和极性 PWMX_CCER1 PWMX_CCER2
6、设置周期时间 PWMX_ARRH PWMX_ARRL
7、使能输出 PWMX_ENO
8、使能主输出 PWMX_BKR
9、启动PWM计时器 PWMX_CR1
10、根据需要调整PWMX_CCCR寄存器的值便可以修改PWM输出的占空比

PWM输出模式应用模式举例: 实现呼吸灯效果
PSW2|= 0X80 ;//扩展寄存器(XFR)访问使能
P4M1=0X0; P4M0=0X0;//P4为准双向
P6M1=0XFF;P6M0=0XFF;//设为开漏
PWMA_PS=0X02;//高级PWM通道输出脚选择位 (查表 10: PWM1P在P6.0/PWM1P_3, PWM1N在P6.1/PWM1P_3)
PWMA_CCER1=0X00;//写CCMRX前必须先清零CCXE关闭通道
PWMA_CCMR1=0X68;//通道模式配置
PWMA_CCER1=0X01;//配置通道输出使能和极性
PWMA_ARRH=(U8)(PWM_PERIOD>>8);//设置周期时间
PWMA_ARRL=(U8)(PWM_PERIOD)&0X00FF;
PWMA_ENO=0X01;//使能输出
PWMA_BKR=0X80;//使能主输出
PWMA_CR1=0X01;//开始计时
PWMA_CCR1H = (U8)(PWM1_DUTY>>8);//设置占空比
PWMA_CCR1L=(U8)(PWM1_DUTY);

互补对称输出(用到PWM1N PWM1P输出)现象:一亮一灭 BLING BLING

PSW2|= 0X80 ;//扩展寄存器(XFR)访问使能
P4M1=0X0; P4M0=0X0;//P4为准双向
P6M1=0XFF;P6M0=0XFF;//设为开漏
PWMA_PS=0X02;//高级PWM通道输出脚选择位 (查表 10: PWM1P在P6.0/PWM1P_3, PWM1N在P6.1/PWM1P_3)
PWMA_CCER1=0X00;//写CCMRX前必须先清零CCXE关闭通道
PWMA_CCMR1=0X68;//通道模式配置
PWMA_CCER1=0X05;//配置通道输出使能和极性  用CC1NP & CC1P
PWMA_ARRH=(U8)(PWM_PERIOD>>8);//设置周期时间
PWMA_ARRL=(U8)(PWM_PERIOD)&0X00FF;
PWMA_ENO=0X03;//使能输出 用到 ENO1N
PWMA_BKR=0X80;//使能主输出
PWMA_CR1=0X01;//开始计时
PWMA_CCR1H = (U8)(PWM1_DUTY>>8);//设置占空比
PWMA_CCR1L=(U8)(PWM1_DUTY);


八路PWM互补对称输出(PWM1P PWM1N、 PWM2P PWM2N 、PWM3P PWM3N、 PWM4P PWM4N)
宏定义引脚输出
宏定义ENO
本地变量声明 标志! _duty  _flag 定时器函数 PWM函数
扩展寄存器(XFR)访问使能

端口设为开漏
道输出脚选择

Flag DUTY初值
定时器初始化、使能中断
清零CCXE关闭通道

通道模式配置
通道输出使能和极性
周期时间
使能输出  从1P到4N
使能主输出
开始计时
给LED供电
打开总中断
while(1)
{
}
初始化定时器0 函数
定时器0中断服务函数
UpdatePWM()子函数
截图202309201517091061.jpg   PWM输出应用!!(操作寄存器方式、操作库函数方式)(智能车--》直弯道变速控制)

捕获模式应用举例:   

测量脉冲周期    读CCRH CCRL
PSW2|=0X80;
P1M1=0X0C;
P1M0=0XF3;
PWMA_PS=0X00;
PWMA_ENO=0XF3;

《手册中用例》 输入捕获模式同时测量脉冲周期和高电平宽度(占空比)   CCx模块  

编码器 在输入模块  AB相输出有相位差  开关信号   定义正转反转, AB相向位,编码原理 ,AB两相接PWM输入PWM1P 和 PWM2P 接口电路,进行处理,重装值0x4F,计数到了该产生中断
截图202309201613281009.jpg 参考芯片手册,例程论坛获取
截图202309201621477234.jpg 截图202309201622249077.jpg


捕获
用内部两个捕获模块,捕获上升和下降沿,检测和计算高电平和周期值,,,精确控计算宽度,尤其是极端情况,例程见手册,

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-21 21:19:19 | 显示全部楼层
《何教授 STC32位8051单片机原理及应用-STC32G12K128》2023/9/19



外设由见到到复杂:From 时钟、复位和电源管理,更好的使用单片机


用前8章处理器内核、汇编语言和C语言,用学到的知识进行驱动和外设的应用


技术上相同之处,ARM图形化界面开发,与STC呈现出来的原理是相同的。三个原理四个典型应用!


子系统-时钟:为处理器、所有外设提供时钟源,时钟子系统结构图
截图202309211535143353.jpg
依据功能和结构分为三级结构:

第一级时钟:
    提供内部高速IRC(EN IRC 寄存器 产生四个频率/时钟信号,多路开关mux1选择,寄存器IRCBAND.SEL器.位)

    外部高速晶振,寄存器EN X OSC
    外部32K晶振,寄存器EN X 32K
    内部32K晶振, 寄存器EN IRC 32K
    内部48M,用于USB,寄存器EN IRC 48M


第二级时钟:
    多路选择器mux2选择输入源(H IRC ,  X osc,  X 32K,  IRC 32K ),寄存器CLKSEL.MCKSEK (选择主时钟),PLL相位锁相环 M级频率
    多路选择器mux3选择输入源(EX32K,  IRC 32K,   ),寄存器RTCCFG.RTCCKS,   RTC时钟 (实时时钟)


    对PLLCKI进行 PCKI 分频,寄存器USBCLK.PCKI (00:/1   01:/2 10:/4  11:/8),送给PLL提供更高的时钟频率,寄存器USBCLK.ENCKM,  PLL输出96M和144M两个固定频率,二选一多路选择器MUX4 ,寄存器CLKSEL.CKMS, 共4个时钟源(PLLCKI,   PLLCLK,   PLLCLK/2,   iirc48m)进MUX5,寄存器CLKSEL.MCK2SEL, 输出主时钟 MCLK,为CPU和外设提供最重要的主时钟


第三级时钟:为CPU和外设产生不同的时钟
    MCLK 经过 CLKDIV 成为 SYSCLK 系统时钟/CPU IAP时钟/其他外部时钟
    CLKDIV后 经过 MCLKODIV 经MUX9 寄存器MCLKOCR.MCLKo_s, 通过P5.4 or P1.6输出


    USB时钟源USBCLK, 48M mux6 mux8,  四种来源
    PWM、SPI时钟源HSCLK,  HSCLKDICV 分频器, MUX7  来源与MCLK或 PLLCLK  
   
寄存器和硬件逻辑行为,寄存器操作功能,二选一、四选一选择器、做分频因子,保证CPU出于理想频率,保证外设处于设定频率,为扩展提供时钟

截图202309211706072116.jpg 存储器映射的寄存器,通过指针定义,见头文件
截图202309211720199168.jpg


复位子系统:硬件复位,所有寄存器恢复到默认值,上电复位,低压复位、复位引脚复位(拉低)、看门狗复位

复位引脚复位,用作IO时失去REST作用


看门狗控制寄存器


软件复位 通过程序代码操作IAP_CONTER 的SWRST触发复位,除了与时钟相关的寄存器保持不变,其余所有寄存器的值都会复位到初始值


电源子系统:低速模式   空闲模式   掉电模式(微安级别  μA)
Idle 仅CPU没有时钟,逻辑状态不变,触发中断,唤醒CPU
power down   没有时钟振荡,主时钟停止振荡,寄存器维持。外部中断,引脚唤醒。  寄存器 PCON


软件复位例程: IAP_CONTR |= 0x20;  //软件复位置1     用了软件复位,从头开始执行程序代码,反复从头执行


看门狗定时器的应用: while(1)
                                     WDT_CONTR |= 0x10;


进入和退出空闲模式:       void  wakeup() interrupt 0
                                     {}
                                       while(1){
                                        PCON |= 0x01;}  //进入IDLE


进入退出掉电模式: WKTCL=0xff;WKTCH=0x80;设置唤醒周期,设能
                              PCON |= 0x02;//触发Power Down

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-22 11:06:19 | 显示全部楼层
《陈教授 1T 8051 单片机原理及应用-STC8H8K64U 》-2023/9/20 - PWM Capt


第一个小例子:利用PWM的脉冲捕获,测量脉冲周期,利用PWM内部某一通道的CC,捕获上升沿或下降沿,计算差值

PWM1P(P6.0)上升沿,在中断中对两次捕获值相减。使用P4.2输出10ms ,占空比2:3的波形,杜邦线飞线物理连接

P_SW2 |= 0下80;//扩展寄存器(XFR)访问使能
P4.2 推挽使出 P6.0高阻输入 STC-ISP IO设置小工具

PWMA_PS=0X02; // pwm通道输出脚位择位 PWM1P: P6.0

PWMA_PSCRH=0X00; PWMA_PSCRL = 0X09; //预分频寄存器   设计原则:系统时钟11.0592Mhz,可捕获波形最大周期65536/11.0592M = 5.926 ms

PWMA_CNTRH=0X00; PWMA_CNTRL=0X00; //计数器清0
PWMA_CCER1=0X00; //关闭PWM通道1

PWMA_CCMR1=0X01; // CC1为输入模式,且映射到TI1FP1上
PWMA_CCER1 =0X01; //使能CC1上的捕获功能
PWMA_SMCR=0X54; // TS=TI1FP1,SMS=TI1 上升沿复位模式
PWMA_CR1=0X01; //开始计时
PWMA_IER =0X02;//使能CC1中断
PWMA_SR1 &=~0X02;//标志清零

第二个小例子:测量高电平的宽度,两通道CCm和CCn同时捕获外部同一个管脚,一个捕获上升沿、一个捕获下降沿,做减法

由于PWM模块结构,有几个对可以,成对使用

核心代码,配置与前面一样
PWMA_CCMR2=0X02; CC2 映射关系配置
PWMA_CCER1 = 0X31 // 开启,一个上升沿、一个下降沿
开中断,标志位清零

C语言熟练

第三个小例子: 周期和脉冲宽度一起测

应用实例讲解:温度测量

截图202309220814145536.jpg NTF测温


回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-24 04:23:13 | 显示全部楼层

《USB型 1T 8051 单片机原理及应用-STC8H8K64U》--2023/9/20 --通过定时器方式多个任务调度



使用Timer0的16位自动重装来产生1ms节拍,程序使用这个节拍进行任务调度



主函数程序: void main (void) { SYS_Init();  while(1){ Task_Pro_Handler_Callback();}}
void SYS_Init(void){
P_SW2 |= 0x80;  //扩展寄存器使能,开发调试把扩展存储都开起来



void GPIO_config(void)//IO口初始化,准双向 ,P1.0 P1.3为ADC 输入(高阻输入)

{P0M1 = 0x00;   P0M0 = 0x00;  P1M1 = 0x09;   P1M0 = 0x00;   P2M1 = 0x00;   P2M0 = 0x00;   P3M1 = 0x00;   P3M0 = 0x00;  P4M1 = 0x00;   P4M0 = 0x00;   P5M1 = 0x00;   P5M0 = 0x00;  P7M1 = 0x00;   P7M0 = 0x00;}  

Timer_config(); //用定时器0进行惹味调度,定时器0初始化


AUXR = 0x80;    //Timer0 set as 1T, 16 bits timer auto-reload, Auto模式

    TH0 = (u8)(Timer0_Reload / 256);  //宏定义设置时间参数
    TL0 = (u8)(Timer0_Reload % 256);

#define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))       //Timer 0


#define MAIN_Fosc                24000000L


    ET0 = 1;    //Timer0 interrupt enable

    TR0 = 1;    //Tiner0 run


ADC_config();  //通过ADC去采样温度,对应通道ADC相关寄存器进行配置


{ADCTIM = 0x3f;   
    ADCCFG = 0x2f;      
    ADC_CONTR = 0x80;  }


EA = 1;


APP_config();  //每个任务功能进行初始化

         Display_init();

                   void Display_init(void) 数码管显示缓冲区初始化
          RTC_init();
                   void RTC_init(void) 初始化相关变量,数码管显示0
          void adcKey_init(void)  ADCA按键初始化


while (1)
    {
        Task_Pro_Handler_Callback();  //初始化结束后主任务开始执行
    }

          void Task_Pro_Handler_Callback(void)
{
        u8 i;
        for(i=0; i<Tasks_Max; i++)//一条一条进行
        {
                if(Task_Comps.Run) /* If task can be run */
                {
                        Task_Comps.Run = 0;    /* Flag clear 0 */
                        Task_Comps.TaskHook();  /* Run task */
                }
        }
}


typedef struct
{
        u8 Run;               
        u16 TIMCount;         
        u16 TRITime;         
void (*TaskHook) (void); //函数指针

} TASK_COMPONENTS;   


static TASK_COMPONENTS Task_Comps[]=  //定义数组显示任务


{0, 1,   1,   Sample_Display},                /* task 1 Period£º 1ms */
        {0, 10,  10,  Sample_MatrixKey},        /* task 2 Period£º 10ms */
        {0, 10,  10,  Sample_adcKey},                /* task 3 Period£º 10ms */
        {0, 300, 300, Sample_NTC},                        /* task 4 Period£º 300ms */
        {0, 500, 500, Sample_RTC},                        /* task 5 Period£º 500ms */
        /* Add new task here */



OS(每个任务都是死循环,运行、准备、挂起、等待) > 任务调度系统 (基于时间片的(分时))

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-25 09:51:47 | 显示全部楼层
冲哥《触摸按键,RTC, 大电流LED数码管自动刷新显示,大型实战》--2023/7/27--学习笔记



STC MCU 实战演示之触摸电子琴: 数码管驱动LED驱动、触摸按键驱动、PWM转DA扬声器


大电流80mALED数码管自动刷新显示:
IO口直驱,MCU的强大集成LED驱动,  数码管的本质是LED  SEG口和COM口组合控制,   LED矩阵同理


用到的COM、SEG设置位推挽输出
用到的IO口(COM、SEG)设置为大电流模式
用到的IO口打开对应的输出使能
设置驱动模式和LED亮度
设置时钟的分频(刷新率)
写入要显示的数据


开启特殊功能寄存器一定要打开的位
截图202309250815151977.jpg


IO口配置工具,设置为推挽输出,复制代码,高级配置 ,设置驱动电流Strong
截图202309250818025720.jpg

端口设完了

COM使能
SEG使能
数码管打开了
截图202309250829277635.jpg


设置LED 驱动和亮度 LEDCTRL = (1<<7) | (2<<4) | (4<<0);        多位设置方法
截图202309250830194732.jpg


LEDCKS = 7;设置时钟分频,手册算法/定义

截图202309250831352079.jpg


显示内容写入寄存器: 依照实际电路,《LED驱动地址对应表》--显示码表


unsigned int code T_LED_CODE[]=       
{
        0xE034,        //0
        0x4004,
        0xE050,
        0xE044,
        0x4064,
        0xA064,
        0xA074,
        0x6004,
        0xE074,
        0xE064        //9
};

调用:
unsigned char i;


COM4_DC_H = T_LED_CODE>>8;
COM4_DC_L = T_LED_CODE;       

i++

点亮一排LED,电路原理图。

        COM5_DA_H = 0XFF;
        COM5_DA_L = 0XFF;       
#########^^点亮数码管驱动^^^^############

触摸按键: 小工具,上位机自动配置工具辅助开发

最大16路触摸,检测微小电容变化,直接检测。可用单次或连续变化,减少CPU开销,一个引脚做一i个功能最稳定马,没有之一

程序如何配置:
触摸引脚配置为高阻输入
配置同时使用触摸检测和虎摸LED驱动,否
用到的触摸通道使能
设置触摸按键开关频率,参考电压和放电时间   TSCFn
开启触摸功能 TSCTRL 很多设置都在这个寄存器
截图202309250859172333.jpg

触摸按键的本质
截图202309250858499699.jpg


触摸按键驱动:
高阻输入:PxM1,PxM0
LED指示和检测:不用 TSRT=0
触摸使能通道: TSCHEN1 = 0x3f TSCHEN2= 0xff
设置触摸按键的开关频率,参考电压和放电时间: TSCFG1 TSCFG2
开启触摸: TSCTRL = 0x80|0x20
开启触摸中断并保存数据:  IE2  |= 0x80 EA=1 中断服务函数 中断向量大于31的方法:


CSEG AT 11BH

        LJMP 006BH

        END


截图202309250908131262.jpg 截图202309250908308167.jpg


void TKSU_ISR(void) interrupt 13{        u8 j = TSSTA2; if( j & 0x40 ) {                TSSTA2 |= 0x40;        }                if( j & 0x80 )  {                j &= 0x0f; TSSTA2 |= 0x80;                                TK_CNT[j] =  TSDAT;                                if( j==15 )                        TK_OVER = 1;        }}

依据TSSTA2寄存器读取和位定义执行判断和行动;

unsigned int TK_CNT[16];定义数组接TSDATA

截图202309250914042890.jpg


调试,串口显示,移植串口驱动 CtrlC+ V

#include<stdio.h> 字符串处理

SEND_U16(TK_CNT[0]);
                       
sprintf(dat,"Num= %u\r\n",TK_CNT[0]);
PrintString1(dat);


官网上位机程序要看下
#############################^^触摸按键驱动^^^^^^^#####################333

RTC实时时钟,掉电走时 年月日,必须外接晶振 32.768MHz,内部晶振会停镇,所有晶振无电不振,触摸电容

程序如何配置:
启动外部晶振,等待稳定后切换
使能RTC功能
需要写入时间INIxxx,并启动初始化
直接读年月日时分秒寄存器

RTC驱动:

X32KCR = 0X80 +0X40;
        while(!(X32KCR & 1));//手册中有例程



SEND_U16(TK_CNT[0]);

sprintf(dat,"%02d:%02d:%02d\r\n",(int)HOUR,(int)MIN,(int)SEC); 串口显示时间,名称头文件有定义,    先串口发送



if( TK_CNT[0] <7000)                        //按键按下评估
                {
                        COM7_DA_H = 0x80;
                        INIHOUR = 0;
                        INIMIN = 0;
                        INISEC = 0;//清空时间,时间初始化
                        RTCCFG |= 1;
                }
                else                                                       
                        COM7_DA_H = 0x00;



RTC实时时钟,RTC对时,论坛
截图202309250939333877.jpg


###################################RTC实时时钟################################

低功耗和普通IO口都支持外部中断

进入低功耗模式方法
进入低功耗前关闭外设、配置好IO
IO口唤醒方法

都关掉
PCON=0x20进入掉电
唤醒,中断唤醒

#################################低功耗########################################

数据掉电储存

每个扇区512字节,Flash替代EEPROM,FLAsh特点,由FF写00, 有无其他至FF只能擦除

看手册例程,
iap范例程序辅助开发
截图202309250948452378.jpg


#include "reg51.h"
#include "intrins.h"

sfr     P0M1    =   0x93;
sfr     P0M0    =   0x94;
sfr     P1M1    =   0x91;
sfr     P1M0    =   0x92;
sfr     P2M1    =   0x95;
sfr     P2M0    =   0x96;
sfr     P3M1    =   0xb1;
sfr     P3M0    =   0xb2;
sfr     P4M1    =   0xb3;
sfr     P4M0    =   0xb4;
sfr     P5M1    =   0xc9;
sfr     P5M0    =   0xca;

sfr     IAP_DATA    =   0xC2;
sfr     IAP_ADDRH   =   0xC3;
sfr     IAP_ADDRL   =   0xC4;
sfr     IAP_CMD     =   0xC5;
sfr     IAP_TRIG    =   0xC6;
sfr     IAP_CONTR   =   0xC7;
sfr     IAP_TPS     =   0xF5;

void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                                //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

char IapRead(int addr)
{
    char dat;

    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 1;                                //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                             //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

void IapProgram(int addr, char dat)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 2;                                //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                             //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(int addr)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 3;                                //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}

void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;

    IapErase(0x0400);
    P0 = IapRead(0x0400);                       //P0=0xff
    IapProgram(0x0400, 0x12);
    P1 = IapRead(0x0400);                       //P1=0x12

    while (1);
}




#######################################^^^^FLASH^^^^^^###############################
       

       
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-25 16:32:34 | 显示全部楼层
陈教授《STC最新8051单片机原理及应用--STC8H8K64U》(9月25日) -- 学习笔记


DMA     批量数据存储功能     CPU不参与     增加CPU--》交由DMA控制      计算机技术      出发点:一不能丢失快速设备提供出来的数据,二是进一步减少快速设备输入输出操作过程中对CPU的打扰


批量数据传输过程由DMA空竹,完成一批数据传输后,快速设备向CPU发一次中断请求,报告传输结束。


主存储器 DRAM XDATA


截图202309251443158439.jpg 截图202309251445397547.jpg

DMA控制器与CPU共享系统数据总线,执行直接存储器数据传输,DMA和CPU同时访问相同的目标(RAM或外设),DMA请求会暂停CPU访问系统总线若干个周期,总线总裁,循环调度,保证CPU得到一半以上的时间片

DMA 每次传输数据量最大256个字节,即最大缓冲区256字节(128个 int)      双工

各DMA外设对XRAM的DMA读写操作都可以设置4级访问优先级,硬件自动进行XRAM总线的访问仲裁。

DMA模块的使用:8种外设之间
截图202309251456437556.jpg

XRAM <==> XRAM
ADC --> XRAM
SPI <===>XRAM
UARTX  <===>XRAM

相关寄存器介绍:

XRAM存储器和串口2进行数据交换的DMa设置过程L
选择串口2引脚,开漏
设置串口2的工作模式和波特率
继续DMA设置:传输总字节、地址、中断允许、启动DMA自动传输
开CPU总中断
在ISA中,对相应的标志位进行处理

在XRAM开辟256字节的发送缓冲区,利用DMA控制器实现将发送缓冲区的内容通过串口2自动发送缓冲区的数据

利用DMA控制器实现ADC数据自动存储到XRAM中

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2025-03-18 20:40:21

1

主题

75

回帖

345

积分

中级会员

积分
345
发表于 2023-9-28 09:04:31 | 显示全部楼层
寄存器可用来暂存指令、数据等处理对象,可以将其看作是内存的一种(物理上不是),根据种类不同,一个MCU内部会有20~100个寄存器;

主存储器通常使用DRAM Dynamic Random Access Menory

程序是把存储器作为对象来描述的
汇编语言与机器语言基本上一一对应
寄存器中存储的指令(置位)、数据(用于运算的数值,表示内存地址的数值)
程序计数器决定程序流程
存储指令和数据的内存,是通过地址划分的
若程序中存在条件分子和循环,机器语言的指令将程序计数器的值设定为任意地址,而不是加一,跳转指令
标志寄存器,保存正负、溢出、奇偶校验等,跳转条件判断
函数调用处理,通过把程序计数器的值设定成函数的存储地址来实现,再完成函数内部的处理后,处理流程再返回到函数调用点(该函数调用指令的下一个地址)
call指令会把调用函数后要执行的指令地址存储在栈(主内存)中,待函数处理完毕后,在通过函数出口来执行return命令,把保存在栈中的地址设定到程序计数器中
内存地址:0000 0000 ~ FFFF FFFF 需要一个32位的寄存器,即可查看全部的内存地址。 基址寄存器,变址寄存器  START + OFFSET  数组
移位操作使最高位或最低位溢出的数字,直接丢弃
补数,二进制数的各数位全部取反,饭后再将结果加一。
算数右移,负数空出来的高位补1,逻辑右移,补零
浮点数,用符号,尾数,基数和指数这四个部分来表示小数
物理上的(硬件的),逻辑上的(软件的)
A address D data
楼房图
将多字节数据的低位字节存储在内存地位地址的方式成为低字节序little endian,于此相反,把数据的高位字节存储在内存低位的方式称为高字节序。Intel奔腾处理器采用低字节序方式
指针也是一种变量,存储着数据的内存的地址
数组是指多个同样数据类型的数据在内存中连续排列的形式,索引,(栈、队列、链表、二叉树,数组的变形方法)
栈LIFO 队列FIFO
往栈中写入数据PUSH,栈中出数据POP
队列一般是以环状缓冲区ring buffer的方式来实现
链表、二叉树,不用考虑索引顺序就可以对数组元素进行读写操作
链表 在数组各个元素之中,除了数据得值之外,附带上下一个元素得索引,追加和删除数据情况下,使用链表是很高效得
链表扩展,二叉树,在链表得基础上往数组中追加元素时,考虑到数据得大小关系,将其分成左右两个方向表现形式,数据值和两个索引信息。使数据搜索更有效率
页,4KB
段,自定义
DLL 程序运行时可以动态加载Library(函数和数据集合)得文件,  公用,节约内存,内存中只存在这一个MyFun()函数,例
_stdcall
扇区是对磁盘进行物理读写得最小单位,Window 1扇区 512字节
在Window在逻辑方面(软件方面)对磁盘进行读写得单位是扇区整数倍-簇,不管文件多小,都占一簇
在任何情况下,文件中得字节数据都是连续存储得
“数据 * 重复次数” RLE 形成长度编码算法 RUN LENGTH ENCODING 图像
哈夫曼算法,为各压缩对象文件分别构造最佳得编码体系,并以该编码体系为基础来进行压缩,用二叉树实现
mapping 映射

Macintosh无法运行Windows得程序,运行环境! 运行环境 = 操作系统  + 硬件
Intel得微处理器, 是按照8086 80286 80386 80486 Pentium……这样得顺序不断升级得,因此这些型号得后面都带有86,所以总成×86,32位处理器也称“IA-32”
CPU只能解释其自身固有得机器语言,不同CPU能解释得机器语言得种类也是不同得 。x86 MIPS PowerPC 它们各自得机器语言是完全不同得
机器语言得程序成为本地代码 native code       C编写得等文本文件,源代码  ————》编译--》本地代码,windows安装软件包收录得不是源代码,而是本地代码
Windows操作系统对克服这些硬件构成得差异做出了很大得贡献,同样得本地代码任何机型上都可以运行,在Window中,应用软件并不直接向硬件发送指令(键盘、显示输出等),而是通过windows发送指令来间接实现得,程序员就不用注意内存和IO地址得不同了
即使是windows,也无法吸收CPU类型得差异 (特定CPU特定本地代码),CPU不同,指令集不同,本地代码也不同,,需要利用能够生成各CPU专用得本地代码得编译器,来对源代码进行重新编译
应用程序向操作系统传递指令得途径成为API Application Programming Interface
porting 移植
虚拟机 操作系统
虚拟机得另外一种用法,提供不依赖于特定硬件及操作系统程序运行环境     JAVA语言记述得源代码--》编译--》字节代码(非特定CPU使用得本地代码) ———》字节代码运行环境 Java虚拟机 ——》字节码转换本地代码进行运行

从应用(用户程序)角度看,Java虚拟机就是运行环境

和硬件相近部分 : 引导程序是存储在启动驱动器起始区域得小程序,     得功能是把在硬盘记录得OS加载到内存中运行。(OS 并不能自己启动自己,而是通过引导程序来启动得)
编程语言编写得程序源代码source code 其文件源文件 .c 文本文件     源代码无法直接运行 CPU能解析得并运行得不是源代码而是本地代码得程序。本地 native 母语 CPU得母语是机器语言,转换成机器语言得程序就是本地代码。 源代码翻译成本地代码
Windows中EXE,本地代码,EXE文件内容DUMP一下,把文件内容,每个字节用2位十六进制数表示一下,每个数值都表示某一个命令或者数据。
编译器负责源代码转换成本地代码。编译器本身也是程序一种,所以也需要运行环境。交叉编译,不同CPU使用得不同本地代码。

源代码-》编译器-》.obj 目标文件-》未完成状态->链接器-》链接(静、动态)-》exe
栈是用来存储函数内部临时使用得变量(局部变量),以及函数调用时所用得参数得内存区域;
堆是用来存储程序运行时得任意数据及对象得内存区域;
高级编程语言得机制,使用独自得函数名,然后再编译时将其转换成相应操作系统的系统调用(或多系统调用的组合)

回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-6-30 13:33 , Processed in 0.134636 second(s), 93 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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