tyun1990
发表于 2023-10-21 09:38:57
本帖最后由 tyun1990 于 2023-10-21 13:29 编辑
学习记录(第13课)第一部分课堂笔记:应用模块化编程,每一个模块对应一个 “.C”“.H”的文件。每个函数都要添加函数说明、版本号
//======================================================// 函数名称:// 函数功能: // 入口参数: // 函数返回: // 当前版本: VER1.0// 修改日期: 2023 - 1-1// 当前作者:// 其他备注://======================================================
修饰符extern 用在变量或者函数的声明前,用来说明此变量函数在别处定义的,要在此处引用例如:Temp.c文件需要应用Temp2.C文件变量int i,就可以在Temp2.H中声明 extern int i,之后才能在Temp.c文件中引用v这个变量
bdata 位寻址变量a.c a.hu8 bdata LED=0x00; extern u8 bdata LED;sbit LED0=LED^0; extern bitLED0;sbit LED1=LED^1; extern bitLED1;以下是.C文件标准模板 以下是.H标准模板
按键检测注意点
按键应该10ms(毫秒)检测一次
软件防抖要<30ms 单击按下检测=30mS, 长按检测3秒开始检测,一直按>3000ms(3 秒)表示在一直按着按键
tyun1990
发表于 2023-10-21 20:00:37
学习记录(第13课)第二部分
新学到的知识:按键的用法
以前我们学到的按键用法跟老师的这个区别很大,感谢老师教的新方法。我要消化一下,第13-4的视频要多看一次才能慢慢明白
老师讲的方法是利用宏定义返回状态来读取按键;我们以前学的方法是直接扫描按键值
#include "key.h"
u16 Count = {0,0,0,0,0,0,0,0};
u8LastState = 0; //8位变量 b0=1,代表k0上一次按下过
//========================================================================
// 函数名称: KEY_Deal
// 函数功能: 按键状态读取
// 入口参数: 无
// 函数返回: 无
// 当前版本: VER1.0
// 修改日期: 2023 - 1-1
// 当前作者:
// 其他备注:循环读取八个端口的状态,并将按下的时间赋值给 Count 数组,按下的状态赋值给LastState
//========================================================================
void KEY_Deal(void) //检查所有的按键状态 10ms执行一次
{
u8 i = 0;
for(i=0;i<8;i++) //循环8次 i的取值范围是0-7代表了P30-P37的状态查询
{
if( ~KEY & ( 1<<i ) ) //持续按下,变量+1
{
if( Count<60000 )
Count ++; //按键按下,这个计数变量+1
}
else //按键松开了,变量清0
{
if( Count>0 ) //如果这个变量是按下过的
{
LastState |= (1<<i); //这个变量相应的标志位置位
}
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 //按键松开
//========================================================================
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;
}
}
}
#ifndef __KEY_H
#define __KEY_H
#include "COMM/stc.h" //调用头文件
#include "COMM/usb.h"
//------------------------------引脚定义------------------------------
#define KEY P3 //P32-P35
#define KEY1 2 //按键1
#define KEY2 3 //按键2
#define KEY3 4 //按键3
#define KEY4 5 //按键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
tyun1990
发表于 2023-10-21 20:13:16
本帖最后由 tyun1990 于 2023-10-21 20:17 编辑
新买的书今天到货了,努力学习中!真羡慕他们大学生,有《STC32位 8051单片机原理与应用》教材 和“配套的实验箱”送呢。而我只能买
之前有一个核心板被我干废了,我也是个人才!估计整个论坛只有我会把核心板和OLED屏幕一起干废的了。无奈新买了一块。还有一块是STC8H8K64U核心板
还没来得及焊接排针先拿出来秀一秀
tyun1990
发表于 2023-10-22 10:27:25
本帖最后由 tyun1990 于 2023-10-22 18:26 编辑
学习记录(第14课)
课堂笔记,矩阵键盘扫描程序
#define MateixKEY P1 //定义矩阵按键的引脚
u8 MateixKEY_Read(void) //矩阵按键读取当前是哪一个按钮按下
{
static u8 keystate_last; //表示当前的按钮的上一次的状态值
u8 keystate; //表示当前的按钮的状态值
u8 key_val = 0; //表示当前按键的键码
MateixKEY = 0XC0; //1100 0000
MateixKEY_delay();
keystate = (MateixKEY ^ 0XC0); //0100 0000 ^ 1100 0000 =1000 0000
MateixKEY = 0X0f; //0000 1111
MateixKEY_delay();
keystate |= (MateixKEY ^ 0X0f); //0000 1110 ^ 0000 1111 =0000 0001 | 1000 0000 = 0x81
if( keystate_last != keystate ) //如果说本次获取到的按键状态值和之前的不一样
{
keystate_last = keystate; //把本次的按键状态值写入进去
switch ( keystate ) //返回对应的键码
{
case 0x41: key_val = 1;break;
case 0x42: key_val = 2;break;
case 0x44: key_val = 3;break;
case 0x48: key_val = 4;break;
case 0x81: key_val = 5;break;
case 0x82: key_val = 6;break;
case 0x84: key_val = 7;break;
case 0x88: key_val = 8;break;
default: key_val = 0;break;
}
}
return key_val; //返回最终的键码,没有按下时返回0
}
tyun1990
发表于 2023-10-22 18:25:34
学习记录(第15课)
课堂笔记
要启动外部中断就必须打开IT0=1或者IT1=1,允许外部中断EX0=1、EX1=1,EA总开关打开。为了防止上电误判可以对IE0、IE1清零。
IT0服务子函数
void EX0_isr(void) interrupt 0
{
}
IT1服务子函数
void EX1_isr(void) interrupt 2
{
}
tyun1990
发表于 2023-10-22 20:41:22
学习记录(第15课)课堂笔记
I/O口 中断初始化程序:
P3IM0=0X00;
P3IM1=0XFF; //低电平中断
P2INTE=0X20; //p35中断 0010 0000
I/O口 中断 中断服务程序:
void P3EXIT_Isr(void) interrupt 40
{
u8 intf;
intf=P3INTF; //读取中断标志
if(intf & 0x20) //P35按下? 0x20由来:芯片手册338页
{
P3INTF=0; //读取完后清除中断标志
if(intf&0x04) //P35按下
{
SEG0++;
if(SEG0>9)
SEG0=0;
}
}
}
特别注意,因位Keil软件的原因不能编译中断号>31的程序。需要安装补丁↓
补丁软件下载链接:https://www.stcai.com/filedownload/609391
tyun1990
发表于 2023-10-23 19:38:06
学习记录(第16课)
外部中断
外部中断0初始化:
IT0 = 1;
EX0 = 1;
IE0 = 0;
P3口初始化:
P3IM0=0X00;
P3IM1=0XFF; //低电平中断
P2INTE=0X20; //p35中断0010 0000
主程序需要调用程序
INT0_Init(); //外部中断0初始化
P3Exit_Init();
EA = 1; //总中断开关打开
中断服务子程序:
void P3Exit_Isr(void) interrupt 40
{
u8 intf;
intf = P3INTF; //读取中断标志
if( intf )
{
P3INTF = 0; //清空中断标志位,必须软件清空
if( intf & 0x20 ) //p35按下 0010 0000
{
}
}
}
特别注意:由于Keil的原因,端口号不支持>31!!需要安装补丁,补丁在stcai网站上下载
tyun1990
发表于 2023-10-23 21:15:10
本帖最后由 tyun1990 于 2023-10-24 09:52 编辑
学习记录(第17课)
STC32G系列是集成了12位高速A/D转换器。ADC 的时钟频率范围SYSclk/2/1到SYSclk/2/16。
ADC初始化:
P1M0 = 0x00;P1M1 = 0x01;//设置P10高阻输入
ADCTIM=0X3F;
ADCCFG=0X2F;
ADC_POWER=1;
读取转换后的程序
u16 ADC_Read(u8 no)
{
u16 adcval; //16位整型变量 adcval 用来读取转换后的值
ADC_CONTR &=0xF0; //
ADC_CONTR |= no; //不能改变原来的设置,或等于NO,入口参数决定是第几通道
ADC_START=1;
_nop_();_nop_(); //等待2个时钟
while(ADC_FLAG); //等待ADC转换结束,“ADC_CONTR.5 :ADC_FLAG”
adcval=(ADC_RES<<8)+ADC_RESL;//读取ADC转换的值
return adcval;
}
主程序只需要调用ADC_Read(0) 来读取转换后的值,括号中的0表示ADC_CHS=0000,选择P1.0 的I/O口。
例如temp=ADC_Read(0); //读取P1.0口端口的ADC值
例如:
tyun1990
发表于 2023-10-24 10:18:21
学习打卡 第17课 第2部分
ADC中断初始化:
P1M0 = 0x00;P1M1 = 0x01;//设置P10高阻输入
ADCTIM=0X3F;
ADCCFG=0X2F;
ADC_POWER=1;
EADC=1; //多了一个EADC
void ADC_Isr() interrupt 5 //ADC的中断是 5
{
ADC_FLAG = 0; //清中断标志
Read_RES=(ADC_RES<<8)+ADC_RESL;//读取
ADC_START=1;//一直转换读取ADC值
}
预编译(红字部分):
#ifndef __ADC_H
#define __ADC_H
#define ADC_CHECK0 //查询
#define ADC_Isr 1 //中断
#defineADC_FuncADC_Isr //最终选择
extern u16 adc_val; //中断获取到的的数值。extern u16表示在其他地方定义了某个变量,在这里调用
void ADC_Init( void ); //ADC初始化
u16ADC_Read( u8 no ); //读取指定通道的adc电压
u16 ADC_CAL_Voltage(u16 num);
#endif
#include "adc.h"
#if ADC_Func == ADC_CHECK
void ADC_Init( void )//adc查询的相关定义
{
//ADC初始化其他程序
}
#elif ADC_Func == ADC_Isr
void ADC_Init( void )//adc中断的相关定义
{
//ADC初始化其他程序
}
#else
#endif
由以上程序可见,有多个void ADC_Init( void ) 的初始化程序时,就可以用到预编译
tyun1990
发表于 2023-10-25 09:25:46
本帖最后由 tyun1990 于 2023-10-25 15:10 编辑
学习打卡,虽然已经学到第18课了,突发奇想想自己写一个矩阵键盘的实验,作业,作业为复习一下第14课老师教的
(↓4*4矩阵键盘,打错了↓)
用到的模块:
main.c:
#include <STC32G.H>
#include "TM1638.H"
//#include "intrins.h"
#include "DELAY.H"
#include "MateixKEY.H"
unsigned char TEMP,temp1;
//unsigned char KeyNum=0,SMG_WEI=2,Tube; //KeyNum用来读取按键值,SMG_WEI用来在哪一个数码管位显示,Tube为数码管当前值
//unsigned char LED_Num=0,LED_SW; //LED_Num用来操作哪一个LED灯,调节范围0-7。LED_SW用过来操作LED灯亮还是灭,0为灭1为亮
//unsigned char LianDu=0; //LianDu用来条件数码管和LED灯的亮度,调节范围0~5,上电默认最低亮度
void main()
{
P0M0=0x00;P0M1=0x00;
P2M0=0x00;P2M1=0x00;
P3M0=0x00;P3M1=0x00;
P4M0=0x00;P4M1=0x00;
TM1638_Init(5); //TM1638初始化
AddrDisPlay(8,0x5b); //测试用,在第8为显示数字2
while(1)
{
TEMP=MateixKEY_Read();
temp1=TEMP;
// AddrDisPlay(SMG_WEI,TubeTab); //更新数码管显示 AddrDisPlay(第几位,显示几);
if(TEMP)
{
AddrDisPlay(1,TubeTab);//数码管刷新
}
}
}
工程目录树:
MATEIX_KEY.C:
#include <STC32G.H>
#include "MateixKEY.H"
#include "DELAY.H"
unsigned char MateixKEY_Read(void) //矩阵按键读取当前是哪一个按钮按下
{
unsigned char KeyNumber=0;
P4=0xff;
P43=0;
if(P47==0){Delay(10);while(P47==0);Delay(10);KeyNumber=1;}
if(P46==0){Delay(10);while(P46==0);Delay(10);KeyNumber=5;}
if(P45==0){Delay(10);while(P45==0);Delay(10);KeyNumber=9;}
if(P44==0){Delay(10);while(P44==0);Delay(10);KeyNumber=13;}
P4=0xff;
P42=0;
if(P47==0){Delay(10);while(P47==0);Delay(10);KeyNumber=2;}
if(P46==0){Delay(10);while(P46==0);Delay(10);KeyNumber=6;}
if(P45==0){Delay(10);while(P45==0);Delay(10);KeyNumber=10;}
if(P44==0){Delay(10);while(P44==0);Delay(10);KeyNumber=14;}
P4=0xff;
P41=0;
if(P47==0){Delay(10);while(P47==0);Delay(10);KeyNumber=3;}
if(P46==0){Delay(10);while(P46==0);Delay(10);KeyNumber=7;}
if(P45==0){Delay(10);while(P45==0);Delay(10);KeyNumber=11;}
if(P44==0){Delay(10);while(P44==0);Delay(10);KeyNumber=15;}
P4=0xff;
P40=0;
if(P47==0){Delay(10);while(P47==0);Delay(10);KeyNumber=4;}
if(P46==0){Delay(10);while(P46==0);Delay(10);KeyNumber=8;}
if(P45==0){Delay(10);while(P45==0);Delay(10);KeyNumber=12;}
if(P44==0){Delay(10);while(P44==0);Delay(10);KeyNumber=16;}
return KeyNumber;
}