大亮 发表于 2023-9-19 16:00:47

本帖最后由 大亮 于 2023-9-19 16:02 编辑

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



--》--》启动引导过程!

== 立即数送累加器,累加器送edata



16位立即数送16位寄存器(选择按寄存器规约),寄存器送0x0009内存地址


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

搬移

搬移 符号扩展




数组:
数组在edata中的地址,code中的调用操作edata地址及内容


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

调用堆栈!   地址在什么地方,当前y值是多少
FIB入栈了


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

LARGEWR6 WR4 WR2 WR0   寄存器不够了 放Xdata   !!!!!!!


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


       函数指针,对于底层 , 间接寻址!

属性!__attribute__

   映射 别名 隐藏信息


__aligned()__
   对齐   分配存储空间的位置
   

noreturn

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

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

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

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

预定义的宏C251编译器提供了一下预定义的宏: 。。。。。




预处理器~



大亮 发表于 2023-9-20 04:44:15

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



周五上午9:00~12:00

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


单片机基础设计硬件知识


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


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


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

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

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

某种意义上的图形化操作,代替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);


动态分配

综合设计实例

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


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

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

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

代码review

#ifndefSTC32G12K128_SYMBOL
#defineSTC32G12K128_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={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};   // 段码
        char key_record={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原理和应用



大亮 发表于 2023-9-20 10:25:10

本帖最后由 大亮 于 2023-9-20 11:28 编辑

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



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

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

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

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

所有信号都与主时钟对齐


捕获/比较 通道: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状态


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

大亮 发表于 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()子函数
PWM输出应用!!(操作寄存器方式、操作库函数方式)(智能车--》直弯道变速控制)

捕获模式应用举例:   

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

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

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



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

大亮 发表于 2023-9-21 21:19:19

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



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


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


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


子系统-时钟:为处理器、所有外设提供时钟源,时钟子系统结构图

依据功能和结构分为三级结构:

第一级时钟:
    提供内部高速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:/411:/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出于理想频率,保证外设处于设定频率,为扩展提供时钟

存储器映射的寄存器,通过指针定义,见头文件



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

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


看门狗控制寄存器


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


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


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


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


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


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

大亮 发表于 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语言熟练

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

应用实例讲解:温度测量

NTF测温


大亮 发表于 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(每个任务都是死循环,运行、准备、挂起、等待) > 任务调度系统 (基于时间片的(分时))

大亮 发表于 2023-9-25 09:51:47

冲哥《触摸按键,RTC, 大电流LED数码管自动刷新显示,大型实战》--2023/7/27--学习笔记



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


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


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


开启特殊功能寄存器一定要打开的位



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


端口设完了

COM使能
SEG使能
数码管打开了



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



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




显示内容写入寄存器: 依照实际电路,《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 很多设置都在这个寄存器


触摸按键的本质



触摸按键驱动:
高阻输入: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





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

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

unsigned int TK_CNT;定义数组接TSDATA




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

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

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


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

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

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

RTC驱动:

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



SEND_U16(TK_CNT);

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



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



RTC实时时钟,RTC对时,论坛



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

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

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

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

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

数据掉电储存

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

看手册例程,
iap范例程序辅助开发



#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^^^^^^###############################
       

       

大亮 发表于 2023-9-25 16:32:34

陈教授《STC最新8051单片机原理及应用--STC8H8K64U》(9月25日) -- 学习笔记


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


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


主存储器 DRAM XDATA




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

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

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

DMA模块的使用:8种外设之间


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中

大亮 发表于 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
栈是用来存储函数内部临时使用得变量(局部变量),以及函数调用时所用得参数得内存区域;
堆是用来存储程序运行时得任意数据及对象得内存区域;
高级编程语言得机制,使用独自得函数名,然后再编译时将其转换成相应操作系统的系统调用(或多系统调用的组合)

页: 1 2 3 4 [5] 6 7 8 9
查看完整版本: 《STC教学研讨会STC8H/STC32G》--学习记录/学习心得--打卡帖 | 建议送