《8051U深度入门到32位51大型实战教学视频》打卡学习
之前帖子是分散的,故开此贴记录我的学习历程 第一集主要讲了Ai8051U相比STC32G的强悍之处,并通过几个实例展示了一下,对其中频谱分析仪和手写计算器很感兴趣{:4_202:}{:4_202:}{:4_202:} 《8051U深度入门到32位51大型实战教学视频》教学视频第二集,主要讲了一下板载外设,开发环境的搭建和如何下载程序,需要注意的是isp软件要选择24MHz频率,型号选择Ai8051U-32K64 第三集正式开始写程序,学习了Ai8051U空白工程的建立和基础点灯操作原理及实操,学习了基本io口的操作,了解了isp软件也能一键生成io口的配置代码 kloca 发表于 2025-6-9 12:13第三集正式开始写程序,学习了Ai8051U空白工程的建立和基础点灯操作原理及实操,学习了基本io口的操作,了 ...
代码如下
#include "AI8051U.H" //头文件引用
void main()
{
P0M1 = 0; //P0端口为准双向口
P0M0 = 0;
P4M1 = 0; //P4端口为准双向口
P4M0 = 0;
while(1)
{
P40 = 0;
P00 = 0;
}
} 第四集学习了USB不停电下载,省去了每次下载都要按复位键再点击下载的过程,还是很有用的。需要调用STC的USB库,有中断和查询的方式,区别在于是立即下载还是执行完当前程序再下载 第五节学习了USB-CDC串口printf的实现,USB-CDC串口相比于普通串口任意波特率都能工作,学习了进制的知识,如果要用64位变量(double),需要加#pragma float64,还学习了其他C语言基础知识。值得注意的是printf为16位,打印变量可能涉及强制类型转换 第六集学习了GPIO,按键的基本操作,了解了高低电平的阈值,该阈值与施密特触发器是否打开有关,需要注意的是,机械按键按下松开时会有10到20ms抖动,可以用isp软件生成延时函数delay来解决抖动带来的按键状态不稳的问题
代码如下
#include "AI8051U.H" //头文件引用
#include "stc32_stc8_usb.h"
#include "intrins.h" //调用头文件
#define u8unsigned char //8位无符号变量(0-255)
#define u16 unsigned int //16位无符号变量(0-65535)
u8 state = 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 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(); //
}
// //任务1:按下P32按钮灯亮,松开P32按钮灯灭;
// if( P32 == 0 ) //判断P32按钮是否按下
// {
// P00 = 0;
// }
// else
// {
// P00 = 1;
// }
//
// //任务2:按下P32按钮灯灭,松开P32按钮灯亮;
// if( P32 == 1 ) //判断P32按钮是否按下
// {
// P00 = 0;
// }
// else
// {
// P00 = 1;
// }
//任务3:按一下灯亮,按一下灯灭
if( P32 == 0 ) //判断P32按钮是否按下
{
Delay20ms(); //延时20ms消抖
if( P32 == 0 )
{
state = !state; //变量取反 0 1 0 1 0 1
P00 = state;
printf("state:%d\r\n",(int)state);
while( P32 == 0 ); //等待P32松开
}
}
}
}
第七节主要学习了定时器中断,并写了三个任务加深理解,需要注意使用printf打印信息时,如果编码有0xfd会被编译器跳过,需加\xfd,还学习了函数的定义,声明和调用
第八节学习了定时器的调度和模块化编程,通过学习规范了代码,方便了代码管理。使用调度器合理配置每个任务,能避免程序堵塞
任务调度器核心代码如下
#include "task.h"
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);
//========================================================================
// 函数: Task_Handler_Callback
// 描述: 任务标记回调函数.
// 参数: None.
// 返回: None.
// 版本: V1.0, 2012-10-22
//========================================================================
void Task_Marks_Handler_Callback(void)
{
u8 i;
for(i=0; i<Tasks_Max; i++)
{
if(Task_Comps.TIMCount) /* If the time is not 0 */
{
Task_Comps.TIMCount--; /* Time counter decrement */
if(Task_Comps.TIMCount == 0) /* If time arrives */
{
/*Resume the timer value and try again */
Task_Comps.TIMCount = Task_Comps.TRITime;
Task_Comps.Run = 1; /* The task can be run */
}
}
}
}
//========================================================================
// 函数: Task_Pro_Handler_Callback
// 描述: 任务处理回调函数.
// 参数: None.
// 返回: None.
// 版本: V1.0, 2012-10-22
//========================================================================
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 */
}
}
}
页:
[1]