Ai8051U学习打卡记录贴
第一集序言 认识Ai8051U首先要感谢STC能给大家提供这么好的一个学习平台,也感谢冲哥精彩的教学!不是第一次看冲哥的视频了,之前的STC32G教学视频也学到了很多,可惜苦于没有试验箱有些功能也一直没有验证。趁着这次官方送试验箱的活动,跟着冲哥再来重新学习下,顺便记录一下。相比之前的8H8K64U,Ai8051U进步太大了,其中有几个新功能特别吸引我,例如新增的QSPI功能,QSPI-Flash直接DMA-P2P送TFT彩屏,另外新增的I2S功能竟然可以录放音了,想想就让人激动!51单片机中的战斗机8051U必将引领全球新风潮!第二集硬件及工具介绍
先喊口号,哪怕梦想让我们拼的遍体鳞伤,这一次我们也要勇往直前!这一节课冲哥主要对8051U试验箱的硬件布局及软件进行了介绍,说实话试验箱做到这个样子官方是真的用心了,有了这个试验箱普中啥的瞬间就不香了!申请试验箱主要是为了体验Ai8051U新产品,研究下QSPI跟IIS,最近也对各种屏幕的驱动兴趣正浓,手里有各种屏,IIC的OLED屏、SPI的TFT屏、又搞了一块16位的屏幕,配合试验箱很有搞头!软件方面的话,8051U支持C51和C251两种模式,相当于8H8K64U跟32G12K128的合体。
编译环境的配置这里不再赘述,喜欢电子的同志们都是高素质人才,阅读英文datasheet都没问题,照着教程安装软件当然也一点问题也没有。下载编译因为之前摆弄过屠龙刀,这里也一语带过。总体来说8051U的试验箱比屠龙刀要强的多了,8051试验箱伴您扬帆起航!
第三集 点亮第一颗LED
这一集冲哥主要讲了如何创建一个新的工程并输入代码,编译下载并运行程序。
因为我手头有STC32G的屠龙刀开发板,因此电脑上已经装了Keil C251,这部分需要重点了解的是IO口的配置。
Ai8051U跟STC32G系列一样IO口有四种工作模式:准双向口、推挽输出、开漏模式、高阻输入,可以通过配置寄存器来设置端口的初始化状态:
对于初学者来说,点亮LED灯很经典,跟学习C语言时输出“Hello,World!”一样让人振奋,以下是用屠龙刀开发板成功在四位共阴数码管上显示时间:
第四集 USB不停电下载
这一集冲哥主要讲了USB不停电下载的方法,这个功能主要是为了方便调试。
常规的下载方法需要按住P3.2不松手,保证芯片上电时P3.2口处于低电位,然后才能进入烧写模式。如果需要频繁更新程序每次都要按压按键实在太麻烦,使用USB不停电下载的方式可以大大的简化操作流程。具体的方法是:
1.从官网下载所需的USB库文件和例程,下载的例程中有多个文件夹可选,冲哥推荐用查询模式+CDC这一个。
2.创建一个新的工程并添加头文件stc32_stc8_usb.h和stc_usb_cdc_32.LIB到工程里面。
3.添加usb_init()函数,进行USB初始化,LIB文件只能调用,无法跟.c文件一样正常在Keil中打开。
4.复制添加以下命令参数(注意代码的命令需要与ISP软件一致):
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
5.设置P_SW2 |=0X80;来打开 EAXFR,然后打开USB中断,打开总中断。
总的来说,照着冲哥的教程来,USB不断电下载还是挺简单的,如果实在理解不了,直接套用冲哥的框架就好。
第五集C语言基础这一节课冲哥主要是给大家恶补了一下C语言的基础知识, C语言是51单片机编程的灵魂所在,即使不是学计算机专业的相信大家在大学期间也已经初步接触过C语言了。大家如果想要更深入学习C语言也可以从网上找到一大堆的教程。冲哥主要讲了以下几大块内容:1、介绍了printf函数在调试单片机时的重要作用。通过printf函数来显示打印信息非常有用,可以将printf函数插入到需要看结果的任意位置,比如执行完某个操作输出1,那么只要输出了1就证明前面的动作已经完成,这在排查错误调试程序时可以快速定位问题点所在。2、讲解了2进制、10进制、16进制的区别及转换方法,这里重新复习了解下:3、讲解了数据的基本类型。这里借用何老师的部分讲义内容,需要大家熟练的掌握几种常用的数量类型。其中数据类型bit、sbit、sfr不是ANSI C中所提供的数据类型,它们是针对Cx51编译器的扩展类型,针对于8051单片机架构。4、讲解了C语言中常用的运算符,常用的有以下几种:+-*/(加减乘除)。其中有个知识难点,++i和i++的含义是不一样的,新手很容易搞糊涂了:C语言的学习没有终点,用到哪块学哪块,要能直接看到学习的结果,这样不会感觉枯燥。
第六集I/O 输入输出
GPIO既General Purpose Input/Output Ports,指通用的输入/输出接口,单片机就是通过引脚输出高低电平或者通过引脚读取外部电平状态是高还是低来实现控制功能的。
Ai8051U的引脚有四种工作模式:准双向口、推挽输出、高阻输入、开漏输出。可以通过软件对端口模式进行配置:
其中准双向口电流输出能力很弱,驱动LED指示灯建议要使用灌电流来驱动;另外准双向口需要读取外部状态时,还需要注意先锁存为“1”才能读取到正确状态:
开漏输出这个模式用处很大,例如在系统中有多个IIC设备时能够保证系统的正常运行,另外还可以通过设置开漏模式实现不同器件的电平兼容。
关于按键输入检测,很简单,使用判断语句来实现:if(P32== 0),如果P32端口为低电平时,则执行后续代码:
机械开关在按压时无可避免的会产生抖动,可以采用软件消抖,也可以试试加个小电容实现硬件消抖:
第七集定时器中断
今天继续跟冲哥学习,这一集主要讲了三块:
1.介绍定时器
因为单片机是单核的,同一时间只能处理一个事情,没有特殊情况不能被打断,因此引入了一个特殊的功能,定时器中断。主要有以下作用
(1) 用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作
(2) 替代长时间的Delay,提高程序的运行效率和处理速度(可以打断主循环)
2.定时器的应用
冲哥以一个实例讲解了定时器的具体应用,LED灯三秒取反一次,这期间任意时刻按下按钮,串口打印按键次数。
使用咱们官方的ISP软件中的定时器计算器能够轻松的设定好所需的时间,很方便
AI8051要实现定时器功能必须要设置一些寄存器,冲哥讲的很详细了,示例可以直接用
3.函数的定义、声明及调用
最后代码讲解,函数这块是基础,这里不再赘述。
收到官方赠送的试验箱,感谢姚总,感谢李经理,感谢瞿经理
第八集-定时器周期性调度任务— 实验一:LED1实现0.3秒取反一次,LED2实现0.6秒取反一次,LED3 0.9秒取反一次
Ai8051U确实强大!接之前的学习打卡,按照冲哥的视频中的实验步骤把一些代码及注意事项打出来。
#include"ai8051u.h"
#include"ai_usb.h"
#define MAIN_FOSC24000000UL
u8 LED1_state = 0;
u8 LED2_state = 0;
u8 LED3_state = 0;
u16 count_300 = 0;
u16 count_600 = 0;
u16 count_900 = 0;
void Timer0_Init(void);
void main()
{
EAXFR = 1;
WTST = 0;
CKCON = 0;
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();
EUSB = 1;
Timer0_Init();
EA = 1;
while (DeviceState != DEVSTATE_CONFIGURED);
P40 = 0; // 打开LED供电
while(1)
{
if (bUsbOutReady)
{
usb_OUT_done();
}
if(count_300>=300)
{
count_300 = 0;
LED1_state = !LED1_state;
P00 = LED1_state;
}
if(count_600>=600)
{
count_600 = 0;
LED2_state = !LED2_state;
P01 = LED2_state;
}
if(count_900>=900)
{
count_900 = 0;
LED3_state = !LED3_state;
P02 = LED3_state;
}
}
}
void Timer0_Isr(void) interrupt 1
{
count_300++;
count_600++;
count_900++;
}
void Timer0_Init(void) //1毫秒@24.000MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x40; //设置定时初始值
TH0 = 0xA2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
第八集-定时器周期性调度任务— 实验二:使用数组法实现LED1 0.3秒取反一次,LED2 0.6秒取反一次,LED3 0.9秒取反一次
#include"ai8051u.h"
#include"ai_usb.h"
#define MAIN_FOSC24000000UL
u8 i;
u8 led_state={0,0,0};//定义三个LED的初始状态
u16 count_ms={0,0,0};//定义三个计时变量
void Timer0_Init(void);
void main()
{
EAXFR = 1;
WTST = 0;
CKCON = 0;
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();
EUSB = 1;
Timer0_Init();
EA = 1;
while (DeviceState != DEVSTATE_CONFIGURED);
P40 = 0; // 打开LED供电
while(1)
{
if (bUsbOutReady)
{
usb_OUT_done();
}
if(count_ms>=300)
{
led_state=!led_state;
P00 = led_state;
count_ms = 0; //计数清零
}
if(count_ms>=600)
{
led_state=!led_state;
P01 = led_state;
count_ms = 0; //计数清零
}
if(count_ms>=900)
{
led_state=!led_state;
P02 = led_state;
count_ms = 0; //计数清零
}
}
}
void Timer0_Isr(void) interrupt 1
{
for(i=0;i<3;i++)
{
count_ms++;
}
}
void Timer0_Init(void) //1毫秒@24.000MHz
{
TM0PS = 0x00; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x40; //设置定时初始值
TH0 = 0xA2; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}