神农鼎
发表于 2025-6-28 21:25:21
建议使用 AiCube@STC-ISP 来加快 实验进度
神农鼎
发表于 2025-6-28 21:26:13
mutuka 发表于 2025-6-26 19:25
感谢版大指点。
姚爷这几课最开始就学了,等板子到了先试。
实验箱 可以 【免费+包邮 送】
mutuka
发表于 2025-6-29 12:23:16
第15集
定时器做计数器
7和8 集讲的任务调度, 是主动操作。
做计数器是被动测量。
T0_C/TT1_C/T 设置0是定时器, 设置1 是计数器
M0 和M1 设置 8/16位,是否重载
T1_CT=1;
T1_M0=0;
T1_M1=0;
T1_GATE=0;
TR1 =1;冲爷还是故意写错表演debug
ET1=1; 冲爷还是故意写错表演debug
EA=1;
P3口配置内置上拉电阻
P3PU |= 0x20;这个用isp工具生成
测量脉冲宽度 是脉冲开始时开始定时, 结束时读取。
mutuka
发表于 2025-6-29 23:08:36
试验箱已收到,还有开天斧板子和 usb 烧录器。
开始复习前面的课
神农鼎
发表于 2025-6-29 23:12:13
复习下面的程序
#include <AI8051U.H>
#include "intrins.h" //使用_nop_()函数所必须要包含的头文件,
//否则延时函数中调用的_nop_()函数没有被头文件引用过来,
//会导致编译器找不到这个而函数而报错。
bit int2_flag = 0; //定义1个位变量,INT2事件位变量标志,记录INT2已产生中断
// 供主循环查询INT2是否已产生中断,在主循环中处理INT2的中断事件任务,不堵塞其他中断
bit int3_flag = 0; //定义1个位变量,INT3事件位变量标志,记录INT3已产生中断
// 供主循环查询INT3是否已产生中断,在主循环中处理INT3的中断事件任务,不堵塞其他中断
void main (void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的 xdata 速度,赋值为 0 表示用最快速度访问,
//不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00;
P3M0 = 0x00; P3M1 = 0x00; //P36、P37设置为准双向口
P4M0 = 0x00; P4M1 = 0x00;
P5M0 = 0x00; P5M1 = 0x00;
P6M0 = 0x00; P6M1 = 0x00;
P7M0 = 0x00; P7M1 = 0x00;
P3PU = 0xc0; //P36、P37打开上拉电阻
AUXINTIF = 0x00; //清空INT2、INT3的中断标志位,防止仿真的时候被错误触发一次
EX2 = 1; //使能 INT2 中断,固定只有下降沿中断
EX3 = 1; //使能 INT3 中断,固定只有下降沿中断
EA = 1; //总中断允许位打开
P40 = 0; //打开LED灯供电
P36 = 1; //INT2所在I/O端口
NOP12(); //可以作为断点插入,用于观察现象
P36 = 0; //手动创造下降沿,这里就会直接跳转到INT2中断了
NOP12(); //芯片内部对下降沿信号进行采样,此处不可设置断点
NOP12(); //可以作为断点插入,用于观察现象
P37 = 1; //INT3所在I/O端口
NOP12(); //可以作为断点插入,用于观察现象
P37 = 0; //手动创造下降沿,这里就会直接跳转到INT3中断了
NOP12(); //芯片内部对下降沿信号进行采样,此处不可设置断点
NOP12(); //可以作为断点插入,用于观察现象
P37 = 1; //手动创造上升沿,此时不会进入中断
NOP12(); //不会进入中断,用于观察现象
NOP12(); //可以作为断点插入,用于观察现象
while(1)
{
if(int2_flag) //主循环中查询,INT2是否已产生中断,是否有需要处理的INT2事件
{
int2_flag = 0; //清0,INT2事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(int3_flag) //主循环中查询,INT3是否已产生中断,是否有需要处理的INT3事件
{
int3_flag = 0; //清0,INT3事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
}
}
void int2_isr(void) interrupt INT2_VECTOR
{
int2_flag = 1; // int2_flag置1是通知主循环处理部分INT2中断事件不需要特急处理的任务
//置1,记录INT2已产生中断,供主循环查询判断有无需处理的INT2任务
P00 = 0; //点亮P00端口上的LED灯
NOP12(); //可以在这里插入断点观察现象
P00 = 1; //关闭LED灯
}
void int3_isr(void) interrupt INT3_VECTOR
{
int3_flag = 1; // int3_flag置1是通知主循环处理部分INT3中断事件不需要特急处理的任务
//置1,记录INT3已产生中断,供主循环查询判断有无需处理的INT3任务
P07 = 0; //点亮P07端口上的LED灯
_nop_(); //可以在这里插入断点观察现象
P07 = 1; //关闭LED灯
}
神农鼎
发表于 2025-6-29 23:12:57
#include <AI8051U.H> //AI8051U的通用头文件,头文件不分大小写
#include"ai_usb.h" //USB库和USB虚拟设备的头文件
//由于在USB库函数的代码中已经定义了,不停电ISP下载命令字”@STCISP#”,
//只需要在下载软件的“收到用户命令后复位到ISP监控程序区”选项卡中进行相应的设置,
//即可实现USB不停电ISP下载功能,或串口不停电ISP下载功能。
bit t0_flag = 0; //定义1个位变量,T0事件位变量标志,记录定时器0已产生中断
// 供主循环查询定时器0是否已产生中断,在主循环中处理定时器0的中断事件任务,不堵塞其他中断
bit t1_flag = 0; //定义1个位变量,T1事件位变量标志,记录定时器1已产生中断
// 供主循环查询定时器1是否已产生中断,在主循环中处理定时器1的中断事件任务,不堵塞其他中断
void Timer0_Isr(void) interrupt TMR0_VECTOR //定时器0中断服务程序
{
P00 = ~P00; //P00灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t0_flag = 1; // t0_flag置1是通知主循环处理部分T0中断事件不需要特急处理的任务
//置1,记录定时器0已产生中断,供主循环查询判断有无需处理的定时器0任务
}
//定时器0中断服务程序,TMR0_VECTOR在AI8051U.H头文件中已宏定义为1
void Timer0_Init(void) //定时器0初始化,2秒@40.000MHz
{
TM0PS = 0x65; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
voidTimer1_Isr(void)interruptTMR1_VECTOR
{
P07 = ~P07; //P07灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t1_flag = 1; // t1_flag置1是通知主循环处理部分T1中断事件不需要特急处理的任务
//置1,记录定时器1已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器1中断服务程序,TMR1_VECTOR在AI8051U.H头文件中已宏定义为3
void Timer1_Init(void) //定时器1初始化,500毫秒@40.000MHz
{
TM1PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x99; //设置定时初始值
TH1 = 0x05; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
voidsys_init(void) //系统初始化
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为0表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的xdata速度,赋值为0表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00; //设置 P0 口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //设置 P1 口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //设置 P2 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //设置 P3 口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //设置 P4 口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
}
voidmain(void)
{
sys_init(); //调用系统初始化函数
usb_init(); //调用USB初始化函数,不需要立即判断电脑已正确识别到USB从设备
/* USB型单片机从设备,如需要主动向电脑发送数据,
在执行USB_SendData( )函数和printf_usb( )函数时,
这两个函数已增加了判断电脑是否已正确识别到USB从设备的程序。
如果电脑要主动发送数据给USB从设备,电脑自己会主动判断与USB从设备是否已正确连接。
*/
EA = 1; //总中断允许位打开
Timer0_Init(); //调用定时器0初始化函数
Timer1_Init(); //调用定时器1初始化函数
P40 = 0; //给LED灯供电
while(1) //主循环中查询需要处理的各种事件,如T0/T1中断事件,并打印输出状态
{
if(t0_flag) //主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t0_flag = 0; //清0,T0事件位变量标志
printf_usb("Timer0!\r\n");
//向电脑USB-CDC串口助手输出“Timer0!”字符串,代表主循环在处理T0不急的任务
}
if(t1_flag) //主循环中查询,定时器1是否已产生中断,是否有需要处理的定时器1事件
{
t1_flag = 0; //清0,T1事件位变量标志
printf_usb("Timer1!\r\n");
//向电脑USB-CDC串口助手输出“Timer1!”字符串,代表主循环在处理T1不急的任务
}
}
}
神农鼎
发表于 2025-6-29 23:13:31
#include <AI8051U.H> //包含AI8051U的头文件
#include"ai_usb.h" //USB库和USB虚拟设备的头文件,需要在项目文件中添加对应的USB库
//由于在USB库函数的代码中已经定义了,不停电ISP下载命令字”@STCISP#”,
//只需要在下载软件的“收到用户命令后复位到ISP监控程序区”选项卡中进行相应的设置,
//即可实现USB不停电ISP下载功能,或串口不停电ISP下载功能。
#include "intrins.h" //使用_nop_()函数所必须要包含的头文件,
//否则延时函数中调用的_nop_()函数没有被头文件引用过来,
//会导致编译器找不到这个而函数而报错。
bit int0_flag = 0; //定义1个位变量,INT0事件位变量标志,记录INT0已产生中断
// 供主循环查询INT0是否已产生中断,在主循环中处理INT0的中断事件任务,不堵塞其他中断
bit int1_flag = 0; //定义1个位变量,INT1事件位变量标志,记录INT1已产生中断
// 供主循环查询INT1是否已产生中断,在主循环中处理INT1的中断事件任务,不堵塞其他中断
bit t0_flag = 0; //定义1个位变量,T0事件位变量标志,记录定时器0已产生中断
// 供主循环查询定时器0是否已产生中断,在主循环中处理定时器0的中断事件任务,不堵塞其他中断
bit t1_flag = 0; //定义1个位变量,T1事件位变量标志,记录定时器1已产生中断
// 供主循环查询定时器1是否已产生中断,在主循环中处理定时器1的中断事件任务,不堵塞其他中断
void Timer0_Init(void) //定时器0初始化,2秒@40.000MHz
{
TM0PS = 0x65; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xB1; //设置定时初始值
TH0 = 0x00; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void Timer1_Init(void) //定时器1初始化,500毫秒@40.000MHz
{
TM1PS = 0x19; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x99; //设置定时初始值
TH1 = 0x05; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
}
void main (void)
{
EAXFR = 1; //允许访问扩展的特殊寄存器,XFR
WTST = 0; //设置取程序代码等待时间,赋值为0表示不等待,程序以最快速度运行
CKCON = 0; //设置访问片内的xdata速度,赋值为0表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00; //设置 P0 口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //设置 P1 口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //设置 P2 口为准双向口模式
//P3M0 = 0x00; P3M1 = 0x00; //设置 P3 口为准双向口模式
P3M0 = 0x00; P3M1 = 0x0c; //P32、P33设置为高阻输入(需要同步开启上拉电阻)
P4M0 = 0x00; P4M1 = 0x00; //设置 P4 口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //设置 P5 口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //设置 P6 口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //设置 P7 口为准双向口模式
P3PU = 0x0c; //P32、P33打开上拉电阻
IT0 = 0; //使能 INT0 上升沿和下降沿中断
// IT0 = 1; //使能 INT0 下降沿中断
EX0 = 1; //使能 INT0 中断
// IT1 = 0; //使能 INT1 上升沿和下降沿中断
IT1 = 1; //使能 INT1 下降沿中断
EX1 = 1; //使能 INT1 中断
IE0 = 0; //清INT0中断标志
IE1 = 0; //清INT1中断标志
int0_flag = 0; //初始化用户标志位
int1_flag = 0; //初始化用户标志位
Timer0_Init(); //调用定时器0初始化函数
Timer1_Init(); //调用定时器1初始化函数
usb_init(); //调用USB初始化函数,不需要立即判断电脑已正确识别到USB从设备
/* USB型单片机从设备,如需要主动向电脑发送数据,
在执行USB_SendData( )函数和printf_usb( )函数时,
这两个函数已增加了判断电脑是否已正确识别到USB从设备的程序。
如果电脑要主动发送数据给USB从设备,电脑自己会主动判断与USB从设备是否已正确连接。
*/
EA = 1; //总中断允许位打开
P40 = 0; //打开LED灯供电
while(1) //主循环中查询需要处理的各种事件,如T0/T1中断事件,并打印输出状态
{
/*本演示程序中,主循环查询各中断有无需要继续处理的事件的次序,
依次是 INT0/INT1/T0/T1, 用户可以自己根据实际情况,
调整查询各中断有无需要继续处理的事件的优先次序*/
if(int0_flag) //主循环中查询,INT0是否已产生中断,是否有需要处理的INT 0事件
{
int0_flag = 0; //清0,INT0事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(int1_flag) //主循环中查询,INT1是否已产生中断,是否有需要处理的INT1事件
{
int1_flag = 0; //清0,INT1事件位变量标志
_nop_(); //用户在此添加需要处理的事件
_nop_();
}
if(t0_flag) //主循环中查询,定时器0是否已产生中断,是否有需要处理的定时器0事件
{
t0_flag = 0; //清0,T0事件位变量标志
printf_usb("Timer0!\r\n");
//向电脑USB-CDC串口助手输出“Timer0!”字符串,代表主循环在处理T0不急的任务
}
if(t1_flag) //主循环中查询,定时器1是否已产生中断,是否有需要处理的定时器1事件
{
t1_flag = 0; //清0,T1事件位变量标志
printf_usb("Timer1!\r\n");
//向电脑USB-CDC串口助手输出“Timer1!”字符串,代表主循环在处理T1不急的任务
}
}
}
void int0_isr(void) interrupt INT0_VECTOR
{
int0_flag = 1; // int0_flag置1是通知主循环处理部分INT0中断事件不需要特急处理的任务
//置1,记录INT0已产生中断,供主循环查询判断有无需处理的INT0任务
if(INT0) //边沿中断,进入后再次判断电平从而判断是什么样的电平
{
// P01 = 0; //判断为高电平,则当前为上升沿,点亮P01端口上的LED灯
// _nop_(); //可以在这里插入断点进行观察现象
// P01 = 1; //关闭LED灯
P01 = ~P01; //如果用外部按键触发INT0,则需另外添加去抖动处理
}
else
{
// P06 = 0; //判断为低电平,则当前为下降沿,点亮P06端口上的LED灯
// _nop_(); //可以在这里插入断点进行观察现象
// P06 = 1; //关闭LED灯
P06 = ~P06; //如果用外部按键触发INT0,则需另外添加去抖动处理
}
}
//INT0中断服务程序,INT0_VECTOR在AI8051U.H头文件中已宏定义为0
void int1_isr(void) interrupt INT1_VECTOR
{
int1_flag = 1; // int1_flag置1是通知主循环处理部分INT1中断事件不需要特急处理的任务
//置1,记录INT1已产生中断,供主循环查询判断有无需处理的INT1任务
// P02= 0; //点亮P02端口上的LED灯
// _nop_(); //可以在这里插入断点观察现象
// P02 = 1; //关闭LED灯
P02 = ~P02; //如果用外部按键触发INT1,则需另外添加去抖动处理
}
//INT1中断服务程序,INT1_VECTOR在AI8051U.H头文件中已宏定义为2
void Timer0_Isr(void) interrupt TMR0_VECTOR //定时器0中断服务程序
{
P00 = ~P00; //P00灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t0_flag = 1; // t0_flag置1是通知主循环处理部分T0中断事件不需要特急处理的任务
//置1,记录定时器0已产生中断,供主循环查询判断有无需处理的定时器0任务
}
//定时器0中断服务程序,TMR0_VECTOR在AI8051U.H头文件中已宏定义为1
void Timer1_Isr(void) interrupt TMR1_VECTOR
{
P07 = ~P07; //P07灯闪烁,中断服务程序中尽量少执行长的任务,防止堵塞其他中断
//以上程序代表部分需特急处理的中断事件,可在中断服务程序中直接处理
//但时间不要太长,否则会影响其他中断事件的实时响应速度
t1_flag = 1; // t1_flag置1是通知主循环处理部分T1中断事件不需要特急处理的任务
//置1,记录定时器1已产生中断,供主循环查询判断有无需处理的定时器1任务
}
//定时器1中断服务程序,TMR1_VECTOR在AI8051U.H头文件中已宏定义为3
神农鼎
发表于 2025-6-29 23:14:39
mutuka
发表于 2025-7-9 01:37:33
第16集
DS18B20 测温
DS18B20 是数字输出。
测温范围 -55 到 +125
可以8个并接在同一组3线
电源 3-5.5
信号 9-12位 串行
试验箱的18b20 需要用跳线帽接入电路
温度数据16位
数据线需要上拉电阻
复位脉冲 480us
存在脉冲 60-240us
操作逻辑复位 CCh 44h 等待 复位 cch beh 读2字节data