那
本帖最后由 327342551 于 2023-12-31 17:00 编辑第九集 数码管 静态
- 数码管 就是一堆小灯,每个灯都是一个 位置led
- 正极接一块的是共阳极 尾椎A,负极接一块是共阴极 尾缀K
- 多位的每一位有一个位选的脚
- 使用时候先位选择,然后在确定点哪几个led
- 二进制转成16进制的数字,做成码表
- 段码是哪4个,位码是哪个
- 用key 控制num,num作为表里面的索引使用 本帖最后由 327342551 于 2024-1-2 13:17 编辑
第十集 动态数码管
- 位选+码表来是一个一个点亮
- 一轮次不要多过20ms
- 先选位,位就是共阴阳极,在让段显示对应的图出来
- 刷新率太低就是交替显示
- 使用数组嵌套的方式来实现了键值对。`P6 = SEG_Tab` 这里的Show_tab 是需要显示的内容。里面的内容是 u8 Show_Tab = {1,5,0,0,7,3,3} v这样实际上,P6就变成了 SEG_Tab num++ 北洋嵌套使用了,其实就是键值对的变相应用。必过很聪明
- 开关类型用 bit 定义,然后直接取反就可以
- 通过取余的方法来实现个十百千位的获取
- 因为是固定的可以不用计算,. 一直要显示 第十一集
定时器
- 定时器每隔一段时间完成一个操作,在后台跑,每隔一段出来一下,中断,处理中断再回去
- 定时器还有计数的功能,所以要先选是定时还是计数的功能
- 原理是加法计数
- 12分频是12周期才走一个,不分频精度高,分频的话定时的时间长
- 自动重载,自动到 65536 然后从 0 计数,不自动重载,到了之后需要手动再去,集中模式通过 T0_M1 和 T0_M0 的组合来实现,不可屏蔽中断的优先级最高,做系统常用。
- 启动定时器的条件
- TF0 = 0 (可写可不写)。溢出中断标志
- TR0 = 1 必须写。启动定时器,必须开
- ET0 = 1 ,启动定时器中断,必须开
- EA = 1 总中断,必须开。
- 直接按 TMOD 来按组编辑寄存器即可
- 定义中断函数 void Tim0_Isr() interrupt 1
- void Tim0_Isr() 这部分就是个普通的函数名字
- interrupt 1 中断号 1,这里需要去查询,不能随便胡写。定时器 0,就是中断号 1.
- void Tim0_Isr() interrupt 1 {} 使能中断
- void Time0_Init(void) 这部分可以通过 stc-isp 的软件来直接配置。不用自己计算
- 中断的频率越低越好 第十二集 计数器
- T1 pin 用来计数
- 计数器主要用来记录脉冲了多少
- 这个计数到头了,重载。和计时器一样
- TH1 TL1都定义成 0xFF 那么只一次就溢出重载算是个技巧
- 直流电机测速示例 第十三集 简单的程序框架
- 功能做成函数和头文件来使用
- keil 里面添加函数的模板
- extern 变量。可以别的文件中去引用。这个关键字不能定义初值
- static 在函数里面才有用,只有第一次赋值时候才有用。第一次定义是0 的话,后面在遇到就不在赋初值
- 引脚定义写到对应的头文件里面去
- 有else if 先执行else if 之后才去执行 else
- 引脚定义、变量声明、函数声明
- if else按键检测
- u8 KE_ReadState(u8 keynum) 这个定义的是一个有返回值的函数,返回值的类型 u8
- 状态机可以出写成switch case的样子,比ifelse 更好
- 状态机是过多长时间采取执行一次,刷新状态
- 其他的程序去取状态就好了
- 定时器比 delay 好多了
- 做 ++ 运算的临时的变量,最后都要重置一下 第十四集 矩阵按键
- 行列的形式来了看具体哪个key按下,4+4 行高电平,列低电平。行低电平列高电平。按了那个去读取就好了
- 位运算,非常的有用,可以减少非常多的判断让程序更快
- 加一个old的状态值,来判断
- switch case 有一个default 都不满足的时候执行的语句
- 每行一个注释,十分有必要
- c语言可以,a = b = c = d = 1;同时赋值 第十五集 外部中断
- 中断就是到了这就到中断里面去执行,完了再出来
- 中断有优先级,已经在低优先级的中断里面执行了,有高优先级的,这时候要到高优先级里面去,高优先级完事,再回到低优先级里面
- 部分优先级可以用软件设置
- 中断的开关
- 总开关 EA = 1
- 每个中断也都有自己的开关
- 每个单片机有哪些去查表,查完再用
- 次数最小,优先级最高
- 外部中断是引脚上电平变化进入中断
- 只能用固定的脚,看图
- 看中断结构图,非常有用,看怎们用中断
- 定义的东西注释一定要清晰,否则错了不好看出来
- 及时响应的用外部中断来实现 stc89c52 定时器头文件改造
这里千万不要使用stc-isp里面的自带的计算器,auxr寄存器功能不一样的,也没有1T的只有12T和6T
头文件使用的stc-isp里面生成的sdcc的库,我的环境为 vscode +sdcc
#ifndef __TIM0_H
#define __TIM0_H
#include <../inc/stc89c5xrc.h>
//------------------------------函数声明------------------------------
void Timer0_Init(void); //1毫秒@12.000MHz
#endif
#include "./TIM/tim0.h"
//========================================================================
// 函数名称: Timer0_Init
// 函数功能: 定时器0初始化
// 入口参数: 无
// 函数返回: 无
// 当前版本: VER1.0
// 修改日期: 2024
// 当前作者:
// 其他备注:
//========================================================================
// 我需要的是定时器0 模式1 16位 定时器
// 公式:(2^16– X)× 12 ÷ 晶振频率 = 定时时间(默认单位us)
// —————————————————————————————————
// X是未知量
// —————————————————————————————————
// 16是根据方式选择的,可以自行选择,方式1为16位
// 方式0 :13 (少用)
// 方式1 :16 (最常用)
// 方式2 :8 (常用)
// 在线计算
// TH0 时间/256
// TL0 时间%256
void Timer0_Init(void) //1毫秒@12.000MHz
{
// AUXR &= 0x7F; //定时器时钟12T模式
// TMOD &= 0xF0; //设置定时器模式
// 以上2句在89c52上不好使 可能软件太老了,
TMOD = 0x01; //设置定时器模式 0000 gate00001 模式 16 位
TL0 =64536%256; //设置定时初始值
TH0 = 64536/256; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
/* //复制这个文件的时候,记得把这个终端还函数复制到主程序里
void Timer0_Isr(void) interrupt 1
{
}
*/
按键扫描 stc89c52
大体基于教学视频修改
#ifndef __KEY_H
#define __KEY_H
#define u8 unsigned char
#define u16 unsigned int
#include <../inc/stc89c52.h>
//------------------------------引脚定义------------------------------
#define KEY P3 //P30-P33 目前可用
// 依次定义是key1-key4 p30-P33
#define KEY1 0 //按键1
#define KEY2 1 //按键2
#define KEY3 2 //按键3
#define KEY4 3 //按键4
//------------------------------变量声明------------------------------
#define KEY_NOPRESS 0 //按键未按下
#define KEY_FILCKER 1 //消抖
#define KEY_PRESS 2 //单击
#define KEY_PRESSOVER 3 //单击结束
#define KEY_LONGPRESS 4 //长按3秒
#define KEY_LONGOVER 5 //长按结束
#define KEY_RELAX 6 //按键松开
//------------------------------函数声明------------------------------
void KEY_Deal(void); //检查所有的按键状态
u8 KEY_ReadState(u8 keynum); //读取指定的按键的状态
#endif
#include "../KEY/key.h"
u16 Count = {0,0,0,0}; // 数组里记录了每一个按键按下的次数
u8LastState = 0; //8位变量 b0=1,代表k0上一次按下过
//========================================================================
// 函数名称: KEY_Deal
// 函数功能: 按键状态读取
// 入口参数: 无
// 函数返回: 无
// 当前版本: VER1.0
// 修改日期: 2024 - 1-2
// 当前作者:
// 其他备注:循环读取四个端口的状态,并将按下的时间赋值给 Count 数组,按下的状态赋值给LastState
//========================================================================
void KEY_Deal(void) //检查所有的按键状态 10ms执行一次
{
u8 i = 0;
for(i=0;i<4;i++) //循环4次 i的取值范围是0-4代表了P30-P33的状态查询
{
if( ~KEY & ( 1<<i ) ) //持续按下,变量+1,没按是1111 1111 0xFF 按下p30是 1111 1110,取反之后是 0000 0001。i=0, 0x00 左移1位是0x01,0的左移只能是1。最后0x01和0x01做与运算。对上了就+1
// 左移符号是 <<,它表示将一个二进制数向左移动指定的位数。例如,1 << 2 表示将二进制数 1 向左移动 2 位,即在二进制数的末尾添加两个 0,得到二进制数 100。左移符号的作用是将一个数乘以 2 的指定次幂。
{
if( Count<6000 ) //u16 最大值65535 不能一直加下去
Count ++; //按键按下,这个计数变量+1
}
else //按键松开了,变量清0
{
if( Count>0 ) //如果这个变量是按下过的
{
LastState |= (1<<i); //这个变量相应的标志位置位,把8个标志位按0-4,依次赋值1
}
else
{
LastState &= ~(1<<i); //这个变量相应的标志位清0,清零单一的标志位
}
Count = 0; //按键按下,这个计数变量清0
}
}
}
//========================================================================
// 函数名称: KEY_ReadState
// 函数功能: 读取指定的按钮的状态
// 入口参数: @keynum : 按钮的端口号 例如P32端口,端口号就是2
// 函数返回: 看其他备注
// 当前版本: VER1.0
// 修改日期: 2023 - 1- 1
// 当前作者:
// 其他备注: 函数返回值如下
#define KEY_NOPRESS 0 //按键未按下
#define KEY_FILCKER 1 //消抖
#define KEY_PRESS 2 //单击
#define KEY_PRESSOVER 3 //单击结束
#define KEY_LONGPRESS 4 //长按3秒
#define KEY_LONGOVER 5 //长按结束
#define KEY_RELAX 6 //按键松开
//========================================================================
// 10ms检测一次
// 高电平 低电平
// 状态 没按下 <30ms 消抖
// 松开 ==30ms 单击
// <3000ms单击结束
// ==3000ms长按
// >3000ms 长按结束
// 总时间计数不超过6000ms,一直加就没头了,还有就是要考虑数据类型 u16的最大是65536
// 下面的keynum 是key1-KEY4 也就是0-3在头文件里面定义的
u8 KEY_ReadState(u8 keynum) //读取指定的按键的状态 10ms执行一次
{
if( Count>0 ) //按键是按下的各种状态返回,用的最上面的数组
{
if( Count<3 ) //按下<30ms 返回消抖状态
{
return KEY_FILCKER;
}
else if( Count==3 ) //按下正好30ms 返回单击
{
return KEY_PRESS;
}
else if( Count<300 ) //按下不到3000ms 返回单击结束
{
return KEY_PRESSOVER;
}
else if( Count==300 ) //按下正好3000ms 返回长按状态
{
return KEY_LONGPRESS;
}
else //长按结束
{
return KEY_LONGOVER;
}
}
else //按键已经松开了,返回各种状态
{
if( LastState &( 1<<keynum ) ) //按键之前按下过
{
return KEY_RELAX;
}
else //按键之前没有按下
{
return KEY_NOPRESS;
}
}
}
stc89c52结合sdcc和stc-isp里面的头文件做的头文件
#ifndef __STC89C52_H__
#define __STC89C52_H__
/////////////////////////////////////////////////
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
/* redefine some keywords */
// primitive type
typedef __sfr sfr;
typedef __sfr16 sfr16;
typedef __sfr32 sfr32;
typedef __sbit sbit;
typedef __bit bit;
// keywords
#define interrupt __interrupt
#define using __using
#define _at_ __at
#define _priority_
#define _task_
// storage type
#define reentrant __reentrant
#define compact
#define small __near
#define large __far
#define data __data
#define bdata
#define idata __idata
#define pdata __pdata
#define xdata __xdata
#define code __code
//包含本头文件后,不用另外再包含"REG51.H"
__sfr __at(0x80) P0;
__sbit__at(0x80) P00;
__sbit__at(0x81) P01;
__sbit__at(0x82) P02;
__sbit__at(0x83) P03;
__sbit__at(0x84) P04;
__sbit__at(0x85) P05;
__sbit__at(0x86) P06;
__sbit__at(0x87) P07;
__sfr __at(0x81) SP;
__sfr __at(0x82) DPL;
__sfr __at(0x83) DPH;
__sfr __at(0x87) PCON;
__sfr __at(0x88) TCON;
__sbit__at(0x8F) TF1;
__sbit__at(0x8E) TR1;
__sbit__at(0x8D) TF0;
__sbit__at(0x8C) TR0;
__sbit__at(0x8B) IE1;
__sbit__at(0x8A) IT1;
__sbit__at(0x89) IE0;
__sbit__at(0x88) IT0;
__sfr __at(0x89) TMOD;
__sfr __at(0x8A) TL0;
__sfr __at(0x8B) TL1;
__sfr __at(0x8C) TH0;
__sfr __at(0x8D) TH1;
__sfr __at(0x8E) AUXR;
__sfr __at(0x90) P1;
__sbit__at(0x90) P10;
__sbit__at(0x91) P11;
__sbit__at(0x92) P12;
__sbit__at(0x93) P13;
__sbit__at(0x94) P14;
__sbit__at(0x95) P15;
__sbit__at(0x96) P16;
__sbit__at(0x97) P17;
__sbit__at(0x91) T2EX;
__sbit__at(0x90) T2;
__sfr __at(0x98) SCON;
__sbit__at(0x9F) SM0;
__sbit__at(0x9E) SM1;
__sbit__at(0x9D) SM2;
__sbit__at(0x9C) REN;
__sbit__at(0x9B) TB8;
__sbit__at(0x9A) RB8;
__sbit__at(0x99) TI;
__sbit__at(0x98) RI;
__sfr __at(0x99) SBUF;
__sfr __at(0xA0) P2;
__sbit__at(0xA0) P20;
__sbit__at(0xA1) P21;
__sbit__at(0xA2) P22;
__sbit__at(0xA3) P23;
__sbit__at(0xA4) P24;
__sbit__at(0xA5) P25;
__sbit__at(0xA6) P26;
__sbit__at(0xA7) P27;
__sfr __at(0xA2) AUXR1;
__sfr __at(0xA8) IE;
__sbit__at(0xAF) EA;
__sbit__at(0xAE) EC;
__sbit__at(0xAD) ET2;
__sbit__at(0xAC) ES;
__sbit__at(0xAB) ET1;
__sbit__at(0xAA) EX1;
__sbit__at(0xA9) ET0;
__sbit__at(0xA8) EX0;
__sfr __at(0xA9) SADDR;
__sfr __at(0xB0) P3;
__sbit__at(0xB0) P30;
__sbit__at(0xB1) P31;
__sbit__at(0xB2) P32;
__sbit__at(0xB3) P33;
__sbit__at(0xB4) P34;
__sbit__at(0xB5) P35;
__sbit__at(0xB6) P36;
__sbit__at(0xB7) P37;
__sbit__at(0xB7) RD;
__sbit__at(0xB6) WR;
__sbit__at(0xB5) T1;
__sbit__at(0xB4) T0;
__sbit__at(0xB3) INT1;
__sbit__at(0xB2) INT0;
__sbit__at(0xB1) TXD;
__sbit__at(0xB0) RXD;
__sfr __at(0xB7) IPH;
__sfr __at(0xB8) IP;
__sbit__at(0xBD) PT2;
__sbit__at(0xBC) PS;
__sbit__at(0xBB) PT1;
__sbit__at(0xBA) PX1;
__sbit__at(0xB9) PT0;
__sbit__at(0xB8) PX0;
__sfr __at(0xB9) SADEN;
__sfr __at(0xC0) XICON;
__sbit__at(0xC7) PX3;
__sbit__at(0xC6) EX3;
__sbit__at(0xC5) IE3;
__sbit__at(0xC4) IT3;
__sbit__at(0xC3) PX2;
__sbit__at(0xC2) EX2;
__sbit__at(0xC1) IE2;
__sbit__at(0xC0) IT2;
__sfr __at(0xC8) T2CON;
__sbit__at(0xCF) TF2;
__sbit__at(0xCE) EXF2;
__sbit__at(0xCD) RCLK;
__sbit__at(0xCC) TCLK;
__sbit__at(0xCB) EXEN2;
__sbit__at(0xCA) TR2;
__sbit__at(0xC9) C_T2;
__sbit__at(0xC8) CP_RL2;
__sfr __at(0xC9) T2MOD;
__sfr __at(0xCA) RCAP2L;
__sfr __at(0xCB) RCAP2H;
__sfr __at(0xCC) TL2;
__sfr __at(0xCD) TH2;
__sfr __at(0xD0) PSW;
__sbit__at(0xD7) CY;
__sbit__at(0xD6) AC;
__sbit__at(0xD5) F0;
__sbit__at(0xD4) RS1;
__sbit__at(0xD3) RS0;
__sbit__at(0xD2) OV;
__sbit__at(0xD1) F1;
__sbit__at(0xD0) P;
__sfr __at(0xE0) ACC;
__sfr __at(0xE1) WDT_CONTR;
__sfr __at(0xE2) ISP_DATA;
__sfr __at(0xE3) ISP_ADDRH;
__sfr __at(0xE4) ISP_ADDRL;
__sfr __at(0xE5) ISP_CMD;
__sfr __at(0xE6) ISP_TRIG;
__sfr __at(0xE7) ISP_CONTR;
__sfr __at(0xE8) P4;
__sbit__at(0xE8) P40;
__sbit__at(0xE9) P41;
__sbit__at(0xEA) P42;
__sbit__at(0xEB) P43;
__sbit__at(0xEC) P44;
__sbit__at(0xED) P45;
__sbit__at(0xEE) P46;
__sbit__at(0xEF) P47;
__sfr __at(0xF0) B;
/////////////////////////////////////////////////
#endif