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