深入学习Ai8051U教学视频打卡
今天学习Ai8051U教学视频第一讲,主要有以下功能:一、 ai8051U相对于STC32G单片机的强化功能部分:
1.优化对QSPI接口的部分flash芯片的读写功能,使屏幕显示和视频播放得到质的提升;并且可充当编程器对flash进行编程下载图像视频文件等等。
2. 支持完整IIS的录放音功能。
3. 增加了PWM支持DMA的功能。
4. 芯片内置硬件浮点乘除单元,能实现频谱分析仪功能。
5. STC单片机从ai8051U开始向AI人工智能单片机转化。
二、 ai8051U脚位兼容89C52,12C5A60S2。
三、 选择不同编译器可以分别兼容8位和32位指令集。
今天学习Ai8051U教学视频第二讲,主要讲解了实验箱的各个硬件组成部分,还有下载软件的各项使用功能。下载软件里集成了很多实用工具,范例程序,I/O口配置,软件延时计算器,定时器计算器等都能极大的方便程序的编写。 学习Ai8051U教学视频第三讲,进行实际程序编写操作了啊。学单片机都是从点亮一个灯开始。
#include "ai8051u.h"
void main(void)
{
P0M0 = 0; //P0端口(P00-P07)为准双向口
P0M1 = 0;
P4M0 = 0; //P4端口为准双向口
P4M1 = 0;
while(1)
{
P40 = 0; //P40端口输出0V,把Led的总开关打开
P00 = 0; //P00端口输出0V,LED1点亮,低电平有效
P01 = 0; //P01端口输出0V,LED2点亮,低电平有效
}
} 学习Ai8051U教学视频第四讲,一个非常有用的功能,就是USB不停电下载,免去了反复按键的麻烦,提高了开发效率。头文件增加#include "stc32_stc8_usb.h" ,并初始化这三个变量
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
在主函数中 增加:
P_SW2 |= 0x80; //B7位写1,使能访问XFR
usb_init(); // 初始化 USB CDC 接口配置
IE2 |= 0x80; // 使能USB中断
EA = 1; // IE |= 0X80;
while (DeviceState != DEVSTATE_CONFIGURED) ; // 等待USB完成配置
在主循环里增加
if (bUsbOutReady)
{
USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
usb_OUT_done();
}
即可! Ai8051U教学视频第五讲,C语言基础。这一章主要讲了printf函数,可以直接通过串口调试助手查看变量的实时变化,大大的提高了程序调试的效率,及时发现问题。还讲了2进制、10进制、16进制之间的关系,数据的基本类型,每种类型的值的范围不一样,定义的时候一定要考虑到,不能超出范围,不然程序会出现意想不到的错误,而且很难发现。最后讲了运算符,活用运算符可以让程序简洁,提高运行效率。
在程序任意位置加上即可,可以添加变量: printf("向上位机发送的信息\r\n"); // 发送消息给上位机 Ai8051U教学视频第六讲,I/O输入输出。本集简要介绍了GPIO,高电平、低电平的概念,当引脚电压为0V代表是低电平,当引脚电压接近于电源正极电压代表是高电平,通过高低电平来判断按键是否按下。其中要加入防抖检测,否则按一下程序会执行多次不可控。把课后小练的程序放上来。
按一下亮一颗灯,再按一下亮两颗灯,直到全亮(变量+加法和乘法)
#include "ai8051u.h" //调用头文件
#include "stc32_stc8_usb.h" //调用头文件
#include "intrins.h" //d调用头文件
#define u8unsigned char //8位无符号变量(0-255)
#define u16 unsigned int //16位无符号变量(0-65535)
u8 state = 0xFF;; //初始状态
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
void Delay20ms(void) //@24.000MHzDelay20ms();
{
unsigned long edata i;
_nop_();
_nop_();
i = 119998UL;
while (i) i--;
}
void main(void)
{
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00;
P1M1 = 0x00; P1M0 = 0x00;
P2M1 = 0x00; P2M0 = 0x00;
P3M1 = 0x00; P3M0 = 0x00;
P4M1 = 0x00; P4M0 = 0x00;
P5M1 = 0x00; P5M0 = 0x00;
P6M1 = 0x00; P6M0 = 0x00;
P7M1 = 0x00; P7M0 = 0x00;
usb_init(); //USB CDC 接口配置
IE2 |= 0x80; //使能USB中断
EA = 1; //IE |= 0X80;
P40 = 0;
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while(1)
{
if (bUsbOutReady) //如果接收到了数据
{
//USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
usb_OUT_done(); //
}
if( P32 == 0 ) //判断P32按钮是否按下
{
Delay20ms(); //延时20ms消抖
if( P32 == 0 )
{
state<<=1;
P0 =state;
if(state==0x00)
state=0XFF;
while( P32 == 0 ); //等待P32松开
}
}
}
} Ai8051U教学视频第七讲,定时器中断。
Ai8051U 系列单片机内部设置了 6 个 24 位定时器/计数器(8 位预分频+16 位计数)。6 个 16 位定时器 T0、T1、T2、T3、T4 和 T11 都具有计数方式和定时方式两种工作方式。
定时器/计数器 0 有 4 种工作模式:模式 0(16 位自动重装载模式),模式 1(16 位不可重装载模式),模式 2(8 位自动重装模式),模式 3(不可屏蔽中断的 16 位自动重装载模式)。
定时器/计数器 1 除模式 3 外,其他工作模式与定时器/计数器 0 相同。T1 在模式 3 时无效,停止计数。
定时器 T2 的工作模式固定为 16 位自动重装载模式。T2 可以当定时器使用,也可以当串口的波特率发生器和可编程时钟输出。
定时器 3、定时器 4、定时器 11 与定时器 T2 一样,它们的工作模式固定为 16 位自动重装载模式。T3/T4可以当定时器使用,也可以当串口的波特率发生器和可编程时钟输出。
我们只要知道需要定时的时间,可以用下载软件里附带的定时器计算器把参数设好直接用。
把作业发上来请指正。
#include "ai8051u.h" //调用头文件
#include "stc32_stc8_usb.h" //调用头文件
#include "intrins.h" //d调用头文件
//注意:擎天柱的LED端口在P2,且没有三极管的电源控制,所以只要控制P2端口即可,按键通用,本节课程的其余内容均通用!
#define u8unsigned char //8位无符号变量(0-255)
#define u16 unsigned int //16位无符号变量(0-65535)
u8 state = 0; //初始状态
u8 Run_State = 0; //运行状态
u8 gongde=0; //功德
u8 tt=0; //判断运行是否到规定时间
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
void Delay20ms(void) //@24.000MHzDelay20ms();
{
unsigned long edata i;
_nop_();
_nop_();
i = 119998UL;
while (i) i--;
}
void Timer0_2SInit(void) //2秒@12.000MHz
{
TM0PS = 0x1E; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xFC; //设置定时初始值
TH0 = 0x03; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void Timer0_1SInit(void) //1秒@12.000MHz
{
TM0PS = 0x0F; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xDC; //设置定时初始值
TH0 = 0x0B; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
void main(void)
{
int count=1; //按键计数变量
WTST = 0; //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0x00;
P1M1 = 0x00; P1M0 = 0x00;
P2M1 = 0x00; P2M0 = 0x00;
P3M1 = 0x00; P3M0 = 0x00;
P4M1 = 0x00; P4M0 = 0x00;
P5M1 = 0x00; P5M0 = 0x00;
P6M1 = 0x00; P6M0 = 0x00;
P7M1 = 0x00; P7M0 = 0x00;
usb_init(); //USB CDC 接口配置
IE2 |= 0x80; //使能USB中断
EA = 1; //IE |= 0X80;
P40 = 0;
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while(1)
{
if (bUsbOutReady) //如果接收到了数据
{
//USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
usb_OUT_done(); //
}
if( P32 == 0 ) //判断P32按钮1是否按下
{
Delay20ms(); //延时20ms消抖
if( P32 == 0)
{
Run_State = !Run_State; //运行状态取反
if( Run_State==1 ) //运行
{printf("双倍功德时间\r\n");
}
else
{
printf("单倍功德时间\r\n");
}
while( P32 == 0 ); //等待P32松开
}
}
if( P33 == 0 ) //判断P33按钮2是否按下
{
Delay20ms(); //延时20ms消抖
if( P33== 0&& tt==0)
{
if( Run_State==1 ) //运行
{
gongde+=2;
printf("功德+2 当前功德:%d\r\n",(int)gongde);
P00 = 0;
Timer0_2SInit();
tt=1;
}
else
{
gongde+=1;
printf("功德+1 当前功德:%d\r\n",(int)gongde);
P00 = 0;
Timer0_1SInit();
tt=1;
}
while( P33 == 0 ); //等待P33松开
}
}
}
}
void Timer0_Isr(void) interrupt 1 //3秒执行一次
{
P00 = 1;
TR0 = 0; //定时器0关闭
tt=0;
}
TT的作用是防止时间没有到1秒或2秒时再次按下P33重新计时,导致亮灯时间不对。欢迎大家指正!
Ai8051U教学视频第八讲,定时器周期性调度任务。用定时器来实现周期性的任务调度,避免了用循环方法,释放单片机资源,提高系统响应速度,改善用户体验。
用一个定时器实现这个任务。LED1实现0.3秒取反一次,LED2实现0.6秒取反一次,LED3 0.9秒取反一次
先是通过数组的方式来定义任务:
static TASK_COMPONENTS Task_Comps[] = {
// 状态计数周期函数
{0, 300, 300, LED0_Blink}, /* task 1 Period: 300ms */
{0, 600, 600, LED1_Blink}, /* task 1 Period: 600ms */
{0, 900, 900, LED2_Blink}, /* task 1 Period: 600ms */
{0, 10, 10, KEY_Task}, /* task 1 Period: 600ms */
};
任务回调处理:
u8 Tasks_Max = sizeof(Task_Comps) / sizeof(Task_Comps);
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 */
}
}
} Ai8051U教学视频第九讲,数码管。
八段数码管由8个发光二极管构成,通过不同的组合可用来显示数字0~9、字符A~F和小数点“.”。分为共阳极和共阴极两种结构。
共阴和共阳的编码是不一样的,程序设计前一定要确定是用共阴还是共阳的数码管!!!
在实际的项目中,多采用动态显示模式。利用人眼的视觉暂留原理,逐位动态扫描显示,可以达到多位视觉上同时显示的效果。
void Send_595(u8 dat)
{
u8 i;
for (i = 0; i < 8; i++)
{
dat <<= 1; // DAT = (DAT<<1); //CY
HC595_SER = CY; // 先把数据写到引脚上
HC595_SCK = 1; // 输出上升沿的时钟信号
HC595_SCK = 0;
}
}
void Display_Seg(u8 HC595_1, u8 HC595_2)
{
Send_595(HC595_1); // 数码管段码输出高电平点亮
Send_595(HC595_2); // 数码管位码 低电平点亮
HC595_RCK = 1; // 数据输出
HC595_RCK = 0;
}
void Seg_Task(void)
{
u8 num = 0;
if (Seg_no == 0) // 小时十位
{
num = shi / 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 1) // 小时的个位
{
num = shi % 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 2) // 第一个横杠
{
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 3) // 分钟的十位
{
num = fen / 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 4)
{
num = fen % 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 5)
{
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 6)
{
num = miao / 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else if (Seg_no == 7)
{
num = miao % 10;
Display_Seg(SEG_NUM, ~T_NUM); // 数码管刷段码和位码
}
else
{
}
Seg_no++;
if (Seg_no > 7)
Seg_no = 0;
}
给大家推荐个数码管编码工具,有些需要特殊字符的时候很方便。
页:
[1]