noonezero
发表于 2023-9-7 11:43:00
本帖最后由 noonezero 于 2023-9-10 07:54 编辑
第九课:数码管的静态使用
1.显示一个数字
数码管显示
代码 我增加了sizeof函数,这样想显示什么,直接在数组上加,不用修改后面的代码
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"
#define KEY1 P32// 功能按键一
#define KEY2 P33// 功能按键二
#define BEEP P54 // 蜂鸣器引脚,低电平响
void sys_init();
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
void Delay_ms(int x) //@24.000MHz
{
unsigned long edata i;
for(; x > 0; x--)
{
_nop_();
_nop_();
_nop_();
i = 5998UL;
while (i) i--;
}
}
void main()
{
u8 SEG_Tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x89, 0xC7, 0xA3, 0x8C, 0xC1};// 这里不写多少也行,会算出来
u8 num = 0;// 显示数组中第几个字符
sys_init();
usb_init();//USB初始化
EA = 1;
P70 = 0;// 开启数码管
while(1)
{
P6 = SEG_Tab;// 显示第几个
if(KEY1 == 0)
{
Delay_ms(10);// 软件消抖
if(KEY1 == 0)
{
BEEP = 0; // 打开蜂鸣器
Delay_ms(10);// 延时
BEEP = 1; // 关闭蜂鸣器
while(KEY1 == 0);// 死循环 等待抬起
if(num < sizeof(SEG_Tab) / sizeof(SEG_Tab))// 算出数组长度
{
num ++;
}
}
}
if(KEY2 == 0)
{
Delay_ms(10);// 软件消抖
if(KEY2 == 0)
{
BEEP = 0; // 打开蜂鸣器
Delay_ms(10);// 延时
BEEP = 1; // 关闭蜂鸣器
while(KEY2 == 0);// 死循环 等待抬起
if(num > 0)
{
num --;
}
}
}
}
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
noonezero
发表于 2023-9-8 10:18:27
本帖最后由 noonezero 于 2023-9-10 09:17 编辑
第十课:数码管的动态显示
动态点亮八个数码管控制原理
P7 开关显示对应数码管对应的值
作业代码
#include <STC32G.H>
#include <intrins.h>
#include "../COMM/stc32_stc8_usb.h"
#define KEY1 P32// 功能按键一
#define KEY2 P33// 功能按键二
#define BEEP P54// 蜂鸣器引脚,低电平响
u8 SEG_Tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xBF
};// 这里不写多少也行,会算出来
bit onoroff = 0;// 开机还是关机
u32 count = 18456000;
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
void sys_init();
void Delay_ms(int x) //@24.000MHz
{
unsigned long edata i;
for(; x > 0; x--)
{
_nop_();
_nop_();
_nop_();
i = 5998UL;
while (i) i--;
}
}
void show(u8 P7index, u8 showtabindex)// P7index 从1开始
{
u8 indexnum = 0x01;
P6 = 0xFF;
P7 = ~(indexnum << (8 - P7index));
P6 = SEG_Tab;
Delay_ms(1);
}
void showinit()
{
show(1, 0);
show(2, 0);
show(3, 10);
show(4, 0);
show(5, 0);
show(6, 10);
show(7, 0);
show(8, 0);
}
void countshow()// count计数显示
{
u32 a = count / 100;// 显示延时了好多,这里如果按1000算 太慢了,100差不多
int mouth =a/(60 * 60);// 求小时
int min =(a - mouth * (60 * 60)) / 60;// 求分
int s = a - mouth * (60 * 60) - min * 60;// 求秒
show(1, (u8)mouth/10);
show(2, (u8)mouth%10);
show(3, 10);
show(4, (u8)min/10);
show(5, (u8)min%10);
show(6, 10);
show(7, (u8)s/10);
show(8, (u8)s%10);
}
void main()
{
sys_init();
usb_init();//USB初始化
EA = 1;
while(1)
{
if(onoroff)
{
count++;
countshow();
}
else
{
showinit();
}
Delay_ms(1);// 延时
if(KEY1 == 0)
{
Delay_ms(10);// 软件消抖
if(KEY1 == 0)
{
BEEP = 0; // 打开蜂鸣器
Delay_ms(10);// 延时
BEEP = 1; // 关闭蜂鸣器
while(KEY1 == 0)// 死循环 等待抬起
{
showinit();
}
onoroff = !onoroff;
count = 0;
}
}
}
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
noonezero
发表于 2023-9-11 08:53:18
本帖最后由 noonezero 于 2023-9-13 13:48 编辑
第十一课:定时器的使用
定时器使用比前十节的视频难度蹭的就上来了
之前的就是简单的I/O操作,配置好模式就只剩下设置高低电平了
定时器这节,刷了几个视频才对定时器,中断有些了解了
简单说,定时器就是按系统时钟,分频下 然后计数脉冲。脉冲计数达到65536 时溢出,产生中断。
计数初始值可以通过 TH0 和 TL0 配置
以下代码通过定时器改了上节课的代码
#include <STC32G.H>
#include <intrins.h>
#include "../COMM/stc32_stc8_usb.h"
#define KEY1 P32// 功能按键一
#define KEY2 P33// 功能按键二
#define BEEP P54// 蜂鸣器引脚,低电平响
u8 SEG_Tab[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xBF
};// 这里不写多少也行,会算出来
bit onoroff = 0;// 开机还是关机
u32 count = 18456000;
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
void sys_init();
void Delay_ms(int x) //@24.000MHz
{
unsigned long edata i;
for(; x > 0; x--)
{
_nop_();
_nop_();
_nop_();
i = 5998UL;
while (i) i--;
}
}
void show(u8 P7index, u8 showtabindex)// P7index 从1开始
{
u8 indexnum = 0x01;
P6 = 0xFF;
P7 = ~(indexnum << (8 - P7index));
P6 = SEG_Tab;
Delay_ms(1);
}
void showinit()
{
show(1, 0);
show(2, 0);
show(3, 10);
show(4, 0);
show(5, 0);
show(6, 10);
show(7, 0);
show(8, 0);
}
void countshow()// count计数显示
{
u32 a = count / 1000;// 显示延时了好多,这里如果按1000算 太慢了,100差不多
int mouth =a/(60 * 60);// 求小时
int min =(a - mouth * (60 * 60)) / 60;// 求分
int s = a - mouth * (60 * 60) - min * 60;// 求秒
show(1, (u8)mouth/10);
show(2, (u8)mouth%10);
show(3, 10);
show(4, (u8)min/10);
show(5, (u8)min%10);
show(6, 10);
show(7, (u8)s/10);
show(8, (u8)s%10);
}
void main()
{
sys_init();
usb_init();//USB初始化
EA = 1;
/**定时器配置**/
AUXR &= 0x7F;//定时器时钟12T模式
TMOD &= 0xF0;//设置定时器模式
TH0 = 0xF8;// 计算出24M时钟下1ms定时时间初始值
TL0 = 0x30;
TR0 = 1;// 启动定时器
EA = 1;// 打开总中断
ET0 = 1;// 使能定时器中断
while(1)
{
if(onoroff)
{
countshow();
}
else
{
showinit();
}
if(KEY1 == 0)
{
Delay_ms(10);// 软件消抖
if(KEY1 == 0)
{
BEEP = 0; // 打开蜂鸣器
Delay_ms(10);// 延时
BEEP = 1; // 关闭蜂鸣器
while(KEY1 == 0)// 死循环 等待抬起
{
showinit();
}
onoroff = !onoroff;
count = 0;
}
}
}
}
void Timer0_Isr(void) interrupt 1
{
count++;
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
noonezero
发表于 2023-9-14 12:07:49
第十二课:计数器的使用
1.开启内部上拉电阻
2.补充中断号
代码
冲哥代码中 TF1 位不用清零,默认就是0,响应中断后会硬件清零
#include <STC32G.H>
#include <intrins.h>
#include "../COMM/stc32_stc8_usb.h"
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
void sys_init();
void Delay_ms(int x) //@24.000MHz
{
unsigned long edata i;
for(; x > 0; x--)
{
_nop_();
_nop_();
_nop_();
i = 5998UL;
while (i) i--;
}
}
void main()
{
sys_init();
usb_init();//USB初始化
P40 = 0;
P3PU = 0x20;// 启动P35上拉电阻
/**定时器配置**/
TMOD |= 0x40;//设置定时器0计数模式
TH1 = 0xFF;// 计算出24M时钟下1ms定时时间初始值
TL1 = 0xFF;
TR1 = 1;// 启动计数器
EA = 1;// 打开总中断
ET1 = 1;// 使能定时器中断
while(1)
{
;
}
}
void Timer1_Isr(void) interrupt 3
{
P6 = ~P6;
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
noonezero
发表于 2023-9-14 21:56:46
本帖最后由 noonezero 于 2023-9-24 15:13 编辑
第十三课:简单多任务处理
1.创建程序文件
[*]新建文件并添加到工程
[*]添加引用路径
引脚定义在.h文件中
sbit 名称 = P10;
#define 名称 P10
2.修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”
extern修饰的变量不能赋初值
3.bdata位寻址变量的使用
4.代码待填
noonezero
发表于 2023-9-24 18:43:38
本帖最后由 noonezero 于 2023-9-25 14:22 编辑
第十四课:什么是矩阵按键
1.原理图
2.实现原理
端口默认高电平,实时读取引脚为低电平表示按下
1. 将P00-P03输出低电平,P06-P07输出高电平,如果有按键按下,按下的那一列IO就会变成低电平,可以判断哪一列按下了
2. 将P00-P03输出高电平,P06-P07输出低电平,如果有按键按下,按下的那一列IO就会变成低电平,可以判断哪一列按下了
3. 行列组合就能知道是哪个按键按下了
3.实现代码:
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"
void sys_init();
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
/*
函数功能:定时器0定时初始化
入口参数:@
函数返回:
其他备注:
*/
void Timer0init()
{
AUXR &= 0x7F;//定时器时钟12T模式 默认就是
TMOD &= 0xF0;//设置定时器模式
TH0 = 0xF8;// 计算出24M时钟下1ms定时时间初始值
TL0 = 0x30;
ET0 = 1;// 使能定时器中断
TR0 = 1; // 开始定时
}
void Delay_ms(int x) //@24.000MHz
{
unsigned long edata i;
for(; x > 0; x--)
{
_nop_();
_nop_();
_nop_();
i = 5998UL;
while (i) i--;
}
}
// 矩阵按键
u8 MateixKEY_Read()
{
u8 keystate; u8 key_val;
// 端口默认高电平,实时读取引脚为低电平表示按下
// 1. 将P00-P03输出低电平,P06-P07输出高电平,如果有按键按下,按下的那一列IO就会变成低电平,可以判断哪一列按下了
P0 = 0xC0; // 1100 0000
Delay_ms(10);
keystate = (P0 ^ 0xC0); // 0100 0000 ^ 1100 0000 = 1000 0000 假设第7位按下
// 2. 将P00-P03输出高电平,P06-P07输出低电平,如果有按键按下,按下的那一列IO就会变成低电平,可以判断哪一列按下了
P0 = 0x0F; // 1100 0000
Delay_ms(10);
keystate |= (P0 ^ 0x0F);
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;
}
u8 SEG_Tab = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x89, 0xC7, 0xA3, 0x8C, 0xC1};// 这里不写多少也行,会算出来
void main()
{
//
u8 num = 0;// 显示数组中第几个字符
sys_init();
usb_init();//USB初始化
//Timer0init();
EA = 1;
P40 = 0;
P70 = 0;
P6 = 0;
while(1)
{
num = MateixKEY_Read();
P6 = SEG_Tab;
}
}
/*
函数功能:定时器0中断执行函数
入口参数:@
函数返回:
其他备注:
*/
void Timer0_Isr(void) interrupt 1
{
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
noonezero
发表于 2023-9-26 18:43:24
本帖最后由 noonezero 于 2023-9-27 07:46 编辑
第十五课:外部中断
1.什么是中断
中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。
当CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后再回到原来被中断的地方,继续原来的工作,这样的过程就叫中断。
2.中断的嵌套
正在执行中断的时候发生优先级更高的中断,会先去执行优先级高的
3.中断结构图
4.什么是外部中断
在单片机引脚上,由于外部因素导致一个电平的变化,跳变。而通过捕获这个变化,单片机内部自主运行的程序就会被暂时打断,转而去执行相应的中断处理程序,执行完后又回到原来中断的地方继续原来的程序
5.程序代码
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"
void sys_init();
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
void Delay_ms(int x) //@24.000MHz
{
unsigned long edata i;
for(; x > 0; x--)
{
_nop_();
_nop_();
_nop_();
i = 5998UL;
while (i) i--;
}
}
void main()
{
//
u8 num = 0;// 显示数组中第几个字符
sys_init();
usb_init();//USB初始化
EA = 1;
IT1 = 1; // 使能INT1下降沿中断
EX1 = 1; // 使能INT1中断
P40 = 0;
P70 = 0;
P6 = 0;
while(1)
{
}
}
void Timer1_Isr(void) interrupt 2 // 外部中断1中断函数
{
P6 = ~P6;
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
问题,我用外部中断0,上下沿和下降沿都可以正常亮灭灯,但是用定时器1就不行,即使配置的是下降沿,上升沿的时候灯依旧会取反一次,我看原理图中有上拉电阻,不清楚原因,先略过,以后解答
noonezero
发表于 2023-9-27 09:54:44
本帖最后由 noonezero 于 2023-10-1 14:47 编辑
第十六课:IO中断
1.什么是IO中断
STC32G系列支持所有的I/O中断,且支持4种中断模式,下降沿中断,上升沿中断,低电平中断,高电平中断。每组IO口均有独立的中断入口地址,且每个IO可独立设置中断模式
2.寄存器相关配置
01使能寄存器配置
02中断标志寄存器
03中断模式配置寄存器
04优先级控制寄存器
2.IO中断的用法
由于中断号大于31,keil不能直接编译,需要下载软件拓展中断号,下载地址深圳国芯人工智能有限公司-工具软件 (stcai.com)
3.中断优先级设置
4.中断代码
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"
void sys_init();
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
void Delay_ms(int x) //@24.000MHz
{
unsigned long edata i;
for(; x > 0; x--)
{
_nop_();
_nop_();
_nop_();
i = 5998UL;
while (i) i--;
}
}
void main()
{
sys_init();
usb_init();//USB初始化
EA = 1;
// P3IO中断配置 下降沿中断
P3IM0 = 0x00;
P3IM1 = 0x00;
P3INTE = 0x20;// 使能P35中断 0010 0000
//P35INTE = 0;// 这种方式不能用
P40 = 0;
P70 = 0;
P6 = 0;
while(1)
{
}
}
void P3Exit_Isr(void) interrupt 40 // 外部中断1中断函数
{
u8 intf;
intf = P3INTF;
if(intf)
{
P3INTF = 0x00;
if(intf & 0x20)
{
P6 = ~P6;
}
}
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
noonezero
发表于 2023-10-2 12:43:48
本帖最后由 noonezero 于 2023-10-4 17:33 编辑
第十七课:模数转换器ADC
1.模数转换器是什么
模数转换器即A/D转换器,简称ADC,通常是指一个将模拟信号转变为数字信号的电子元器件
模拟信号 -> 电压
数字信号 -> 0/1组成的二进制数
如果芯片有ADC的外部参考电源管脚 ADC_VRef+, 则一定不能浮空,必须接外部参考电源或者直接连到VCC。
2.需要配置的寄存器
ADC_POWER:ADC电源控制位,0关闭ADC,1打开。建议进入空闲模式和掉电模式前将ADC电源关闭,以降低功耗;
1. 给MCU的内部ADC模块电源打开后,需等待约1ms,等MCU内部的ADC电源稳定后再让ADC工作。
2.适当加长对外部信号的采样时间,就是对ADC内部采样保持电容的充电放电时间,时间够,内部才能和外部电势相等。
ADC_START:开始转换,转换后自动清0,手动输0不会停止转换
ADC_FLAG:转换结束标志位,转换完成会置1,需要软件清零
ADC_EPWMP:暂空,需要PWM
ADC_CHS:通道选择位,选择好通道需要把对应IO口设置为高阻输入
RESFMT:0转换结果左对齐,1右对齐
SPEED:设置ADC时钟
ADC_RES:转换结果高位
ADC_RESL:转换结果低位
3.ADC速度计算公式
4.ADC转换结果公式
5.反推ADC输入电压计算公式
5.反推工作电压计算公式
6.代码-查询方式
#include "config.h"
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"
#include "stdio.h"
void sys_init();
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
// ADC初始化
void ADC_init()
{
//P10高祖输入
P0M1 &= 0xFE;
P0M1 |= 0x01;
ADCTIM = 0x3F; // 设置ADC内部时序
ADCCFG = 0x2F; // 数据右对齐,方便合二为一。时钟选择为最慢
ADC_POWER = 1; // 打开ADC电源
}
// ADC读取
u16 ADC_Read(u8 num)
{
u16 adcval; // ADC数值保存变量
ADC_CONTR &= 0xF0; // 清空通道
ADC_CONTR |= num; // 选择通道
ADC_START = 1; // 开启ADC转化
_nop_(); // 空操作指令
_nop_();
while(!ADC_FLAG); // 等待ADC转换结束
ADC_FLAG = 0; // 手动清零
adcval = (ADC_RES << 8) + ADC_RESL; // 计算ADC数值
return adcval;
}
void main()
{
u16 ADC_VAL;
sys_init();
usb_init();//USB初始化
EA = 1;
ADC_init();
while(1)
{
if (bUsbOutReady)
{
USB_SendData(UsbOutBuffer, 64);
usb_OUT_done();
}
ADC_VAL = ADC_Read(0);
printf("adcvalue\t%d\r\n",(int)ADC_VAL);
// printf("wenjun\r\n");
}
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
noonezero
发表于 2023-10-5 15:24:12
第十八课:ADC采集电源电压和ADC按键
1.ADC采集电源电压
内部1.19V电源有+-1%误差,可以利用ADC的第15通道反推ADC_VRef+脚外接参考电源电压
#include "config.h"
#include <STC32G.H>
#include "../COMM/stc32_stc8_usb.h"
#include "stdio.h"
#define VREFH_ADDR CHIPID7
#define VREFL_ADDR CHIPID8
int BGV;
void sys_init();
//USB调试及复位所需定义
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
// ADC初始化
void ADC_init()
{
ADCTIM = 0x3F; // 设置ADC内部时序
ADCCFG = 0x2F; // 数据右对齐,方便合二为一。时钟选择为最慢
ADC_CONTR = 0x8F; // 选择通道15
}
// ADC读取
int ADC_Read()
{
int res; // ADC数值保存变量
ADC_START = 1; // 开启ADC转化
_nop_(); // 空操作指令
_nop_();
while(!ADC_FLAG); // 等待ADC转换结束
ADC_FLAG = 0; // 手动清零
res = (ADC_RES << 8) | ADC_RESL; // 计算ADC数值
return res;
}
void main()
{
int res;
int vcc;
int i;
sys_init();
usb_init();//USB初始化
EA = 1;
BGV = (VREFH_ADDR << 8) + VREFL_ADDR; // 从CHIPID中读取内部参考电压值
ADC_init();
ADC_Read();
ADC_Read();
ADC_Read();
ADC_Read(); // 舍弃四个值
res = 0;
for(i=0; i<8; i++)
{
res += ADC_Read();
}
res >>= 3;// res / 8 算平均值
vcc = (int)(4096L * BGV / res);
while(1)
{
if (bUsbOutReady)
{
USB_SendData(UsbOutBuffer, 64);
usb_OUT_done();
}
printf("power \t%d\r\n", vcc);
}
}
void sys_init()
{
WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M1 = 0x32; P1M0 = 0x32; //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
P2M1 = 0x3c; P2M0 = 0x3c; //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V),设置开漏模式需要断开PWM当DAC电路中的R2电阻
P3M1 = 0x50; P3M0 = 0x50; //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
P4M1 = 0x3c; P4M0 = 0x3c; //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
P5M1 = 0x0c; P5M0 = 0x0c; //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
ADC按键,后面补,我的实验箱有点BUG,按键1-5可以用,其他都不行。