macrofei 发表于 2024-12-16 14:10:52

AI8051U实验箱学习记录

<p>第一集心得</p>
<p>在老师的讲解中,我们深入了解了AI8051U的一些应用案例,涵盖了多种功能,并展示了其卓越的性能。以下是我特别关注的几个亮点:<br />
1.彩屏刷新效果:<br />
彩屏刷新率表现非常流畅,能够实现细腻的显示效果,确保了屏幕显示的稳定性和清晰度。<br />
PWM_DMA控制:<br />
2.通过PWM_DMA技术,我们能够同时驱动1000+颗LED灯珠,实现精确的灯光控制。此功能不仅支持高效的频谱显示,还能快速进行FFT运算,并实现实时更新,提升了整体显示效果的响应速度。<br />
IIS录放音功能:<br />
3.支持IIS接口的音频录制与播放,具备暂停录音和播放录音的功能。通过这一功能,用户能够轻松实现高质量的音频录放操作,方便且实用。<br />
智能手写计算器:<br />
4.AI8051U内置的手写识别功能能够智能识别手写数字,快速转换为计算输入,极大地提升了用户体验。<br />
5.Flash编程器与视频显示:<br />
内建的Flash编程器具备强大的视频显示能力,能够顺畅播放视频,演示效果非常出色。<br />
AI8051U展示了其在多项技术上的强大运算能力与应用前景,尤其在PWM_DMA和彩屏显示方面的表现尤为突出,为各种智能设备应用提供了强有力的支持。</p>

macrofei 发表于 2024-12-16 14:11:28

<p>第二集<br />
老师在这一集中详细介绍了 AI8051U实验箱 的各个硬件模块及其应用场景。</p>
<ol>
<li>USB接口与烧录功能<br />
USB-TypeA接口:传统的USB接口,常用于连接电脑和其他USB设备。<br />
USBLink1D接口:专为STC官方烧录工具设计,方便将程序烧录到单片机中。<br />
USB-TypeC接口:提供额外的烧录连接方式,具有更高的数据传输速率和更广泛的兼容性。<br />
USB转双串口:通过官方芯片将一个USB接口转换为两个串口接口,可以实现更多的串口通信,方便进行调试与数据传输。</li>
<li>存储与数据扩展<br />
TF卡插座:能够有效扩展存储容量,适用于需要大量数据存储的应用,如数据采集、音视频存储等。</li>
<li>测量与信号测试<br />
示波器BNC输入:通过外接示波器头,可以测量电路中的波形,进行信号测试和调试,帮助我们理解信号的变化和调试技术。<br />
掉电检测电压:当设备掉电时,能够及时检测到电压变化,并实现程序的掉电恢复功能,这是一个非常实用的功能,能够保证系统在断电后恢复工作。</li>
<li>音频与显示功能<br />
立体声耳机输出:可以连接耳机播放声音,适合音频输出应用。<br />
立体声线路输出:通过此接口可以输出立体声信号,用于音响系统等设备的声音播放。<br />
话筒录音功能:配合AI8051U的录音程序使用,可以实现高质量的录音效果,适合做语音识别、录音分析等应用。<br />
OLED屏幕:小型显示屏,适用于显示简单的信息,如MP3播放器的显示。<br />
TFT彩屏:具有更高分辨率和丰富色彩的显示屏,可以用于更复杂的显示应用,非常期待测试这个功能。</li>
<li>硬件基础与实验功能<br />
8路流水灯:这是进入硬件学习的第一步,通过点亮一系列灯泡模拟流水效果,帮助我们理解输出控制。<br />
8位数码管:由两个4位数码管组合而成,用于显示数字或字符。<br />
矩阵键盘:可以通过按键输入数据,矩阵键盘通过直连IO口或通过ADC计算得到输入值,广泛用于输入接口中。<br />
LCD和RTC时钟功能:LCD用于显示实时信息,RTC时钟可以提供准确的时间跟踪。</li>
<li>通信与传感器功能<br />
红外接收:通过红外遥控器接收信号,可用于遥控操作。<br />
红外发射:可以对其他设备发射红外信号,用于远程控制其他设备。<br />
EEPROM存储:用于存储大容量数据,适合需要持久保存的应用场景,如配置文件、用户数据等。<br />
DS18B20温度传感器:这是一个低成本且高精度的温度传感器,可以用于温度测量应用。<br />
SP3485通信芯片:此芯片提供RS-485通信能力,适合多点通讯和工业自动化系统的构建。</li>
<li>实验与开发工具<br />
Keil软件:Keil是嵌入式开发领域非常经典的集成开发环境,老师介绍了如何使用Keil编写程序、调试代码,并进行单片机编程。<br />
程序烧录与调试:老师展示了如何从STC官网下载所需的文件,解压、编译并烧录到单片机中。<br />
点灯实验:老师演示了如何利用程序控制8位流水灯实现基本的硬件调试。通过调整程序,我们能够学习到如何切换8位和32位的不同模式,并掌握完整的烧录和调试过程。<br />
跑马灯实验:作为基础实验之一,跑马灯实验通过程序控制LED灯逐个点亮,帮助我们理解单片机的时序控制和硬件接口。</li>
<li>其他硬件细节<br />
晶振:位于电路板的背面,晶振在精确校时和系统时钟生成中扮演关键角色,保证系统的时序准确性。</li>
</ol>

macrofei 发表于 2024-12-16 14:11:53

<p>第三集:点亮第一颗LED灯</p>
<ol>
<li>创建空工程与基本设置<br />
新建工程:选择目标平台为 C251,并设置 Large 为 64k,Hex 为 386模式。<br />
工程配置:选择合适的目标芯片型号并进行必要的配置,确保编程环境正常运行。</li>
<li>LED的功能与特性<br />
LED的工作原理:LED灯通过电流的流动来发光,通常需要一个电流限流电阻来保护LED。单片机通过控制I/O口的高低电平来点亮或熄灭LED。<br />
LED的控制:通过配置单片机的I/O口,输出适当的电平来控制LED的亮灭。</li>
<li>单片机I/O口配置与控制<br />
配置I/O口:使用STC公司提供的IO配置工具来设置端口模式,包括准双向口、输入口、输出口等。通过配置端口为输出模式,单片机可以控制LED的亮灭。<br />
IO口控制:在代码中配置相应的I/O口,向I/O口输出高电平(点亮LED)或低电平(熄灭LED)。</li>
<li>代码实现与下载<br />
编写代码:根据硬件连接和I/O口配置,编写点亮LED的程序。例如,通过设置某个端口输出高电平来点亮LED。<br />
下载代码:将编写好的代码下载到单片机中,进行调试和测试,确保LED能够按预期亮灭。</li>
</ol>

macrofei 发表于 2024-12-16 14:12:40

<p>第四集:USB不停电下载<br />
本集主要展示了停电下载和不停电下载的区别,并介绍了如何通过一些设置实现不停电下载。<br />
实现步骤:<br />
添加USB库文件:<br />
首先,添加STC的USB库文件到工程中,以支持USB通信。<br />
移植下载函数:<br />
将相关的下载函数移植到你的代码中,使其能够支持不停电下载功能。<br />
配置初始化:<br />
在代码中添加USB初始化函数,确保USB接口能够正常工作。<br />
烧录工具设置:<br />
打开烧录工具,勾选命令参数选项,这样可以使工具支持相应的命令行参数。<br />
设置相关寄存器:<br />
配置P_SW2寄存器或IE2寄存器,启用USB功能并确保不停电下载过程顺利进行。</p>
<p><img src="data/attachment/forum/202412/16/141227ifoeoovv6oj33oce.png" alt="image.png" /></p>

macrofei 发表于 2024-12-16 14:13:44

<p>第三集补充</p>
<p><img src="data/attachment/forum/202412/16/141315koo63tfon86nodeg.jpg" alt="69b24bcb18beb3d354208db46b920b7.jpg" /><img src="data/attachment/forum/202412/16/141326i8dqvo76z144muou.png" alt="image.png" /></p>

macrofei 发表于 2024-12-16 14:14:40

<p>第五集:C语言基础<br />
在这一集的学习中,我们进一步深入了C语言的一些核心概念和语法,包括输出函数的使用、数据类型之间的关系、变量的作用域、宏定义的应用以及各种常用运算符的功能。</p>
<ol>
<li>printf 函数<br />
printf 函数是C语言中最基本的输出函数之一,用于将数据输出到屏幕上。通过格式化输出,printf 不仅可以输出普通文本,还能显示变量的值、格式化数据(如浮点数、字符串等)。printf 的格式化符号使得我们能够控制输出的形式,比如输出整数、浮点数、字符串等数据类型。</li>
<li>Hex与文本之间的关系<br />
在C语言中,十六进制(Hexadecimal)常用于表示数字和内存地址。十六进制是一种以16为基数的计数系统,它可以更简洁地表示二进制数。十六进制数的常用前缀是 0x。当在程序中需要查看或操作内存时,十六进制尤其重要,因为它能有效简化复杂二进制数的表示。</li>
<li>变量的范围(作用域)<br />
变量的范围或作用域指的是变量在程序中的有效区域。在C语言中,变量主要分为全局变量和局部变量:<br />
全局变量:在 main 函数外部声明的变量,整个程序中的所有函数都可以访问这些变量。<br />
局部变量:仅在声明它们的函数或代码块内有效。当函数执行结束时,局部变量的生命周期也结束。<br />
理解变量的作用域对于编写结构清晰且无错误的程序至关重要。在使用全局变量时要特别小心,以避免不小心修改其值。</li>
<li>宏定义的使用<br />
宏定义是C语言中的预处理指令,通过#define可以给常量或表达式起一个别名。宏定义在编译阶段会被直接替换为定义的值。它与普通变量不同,因为宏在预处理阶段进行替换,因此没有类型检查,容易导致错误。宏定义常用于常量、条件编译等场景。<br />
例如,宏常用来定义常量,使得程序中的常量更加易于管理和修改。</li>
<li>变量与宏定义的关系<br />
变量与宏定义的最大区别在于:变量在程序运行时有实际的内存地址,而宏定义只是文本替换,不会占用内存空间。宏常用于程序中那些不会改变的值,如常量或者控制标志。这种替换机制使得代码在编译时更加高效,但也需要注意宏带来的潜在问题,如优先级错误、调试困难等。</li>
<li>运算符的作用<br />
C语言提供了丰富的运算符,用来执行各种数学、逻辑和位操作:<br />
算术运算符:包括加、减、乘、除、取余等,用于执行基本的数学运算。<br />
关系运算符:用于比较两个值的大小,如相等、不等、大于、小于等。<br />
逻辑运算符:用于逻辑判断,主要有与(&amp;&amp;)、或(||)、非(!)运算符,它们常用于条件判断中。<br />
位运算符:包括按位与(&amp;)、按位或(|)、按位异或(^)、取反(~)、左移(&lt;&lt;)和右移(&gt;&gt;)。这些运算符通常用于二进制数据的操作。<br />
这些运算符的使用使得C语言程序能够进行高效的数值运算和逻辑判断。了解这些运算符的特性和作用,有助于更好地编写复杂的程序逻辑。</li>
<li><img src="data/attachment/forum/202412/16/141429pakv2ck3hk7ppk3v.png" alt="image.png" /></li>
</ol>

macrofei 发表于 2024-12-16 14:15:39

<p>第六集:IO输入输出</p>
<ol>
<li>GPIO的输入电压范围<br />
GPIO引脚的输入电压范围通常取决于微控制器的工作电压:<br />
3.3V系统:输入电压通常在0V到3.3V之间,超过3.3V可能损坏芯片。<br />
5V系统:输入电压通常在0V到5V之间。<br />
逻辑电平判定:<br />
低电平(0):0V到0.8V。<br />
高电平(1):2V到3.3V(3.3V系统)或2V到5V(5V系统)。<br />
注意:不同芯片的电压阈值可能有所不同,开发时需要参考芯片文档。</li>
<li>四种常用GPIO模式<br />
GPIO引脚可以配置为以下四种模式:<br />
输入模式:用于读取外部信号。<br />
输出模式:用于驱动外部设备,例如LED。<br />
推挽输出模式:提供高电平和低电平驱动能力,适合高电流负载。<br />
开漏输出模式:只拉低电平,需要外部上拉电阻来实现高电平。</li>
<li>电压的有效范围<br />
在GPIO输入模式下:<br />
低电平:通常是0V到0.8V(具体阈值依芯片而定)。<br />
高电平:一般是2V到Vcc(例如3.3V或5V)。<br />
输入电压超出这个范围可能会导致硬件损坏。</li>
<li>按键输入检测<br />
按键输入通常通过GPIO引脚来检测。常见的两种方式是:<br />
上拉电阻方式:按键未按下时,GPIO通过上拉电阻接到Vcc(高电平);按下时,GPIO引脚接地(低电平)。<br />
下拉电阻方式:按键未按下时,GPIO通过下拉电阻接地(低电平);按下时,GPIO引脚接到Vcc(高电平)。<br />
GPIO读取按键状态时,如果是高电平则认为按键未按下,低电平则认为按键被按下。</li>
<li>接地导通为0V<br />
许多按键电路设计使用接地导通的方式,即按键按下时GPIO引脚接地,读取为低电平(0V);按键松开时,GPIO通过电阻连接到Vcc,读取为高电平(1)。</li>
<li>按键点灯操作<br />
按键控制LED的点亮是常见的GPIO应用。通过读取按键的状态来控制LED的开关:<br />
按下按键:GPIO输出高电平(1),点亮LED。<br />
松开按键:GPIO输出低电平(0),熄灭LED。</li>
<li>按键抖动消抖处理<br />
按键按下和松开时,可能会产生短暂的电气抖动,导致误触发。为此,我们需要进行消抖处理。<br />
硬件消抖:通过电容滤波,平滑按键信号。<br />
软件消抖:在读取按键状态时,引入延时或多次采样确认按键稳定。<br />
简单的软件消抖方法是:在按键状态变化时,等待一段时间再确认状态是否稳定。</li>
</ol>
<pre><code class="language-html">        //课后任务1
        if( P32 == 0 )                                                                //判断P32按钮是否按下
        {
                Delay20ms();                                                        //延时20ms消抖
                if( P32 == 0 )
                {
                        state = !state;                                                //变量取反 0 1 0 1 0 1
                        P22 = 1;
                        printf(&quot;state:%d\r\n&quot;,(int)state);

                        while( P32 == 0 );                                        //等待P32松开

                }
        }
        if( P33 == 0 )                                                                //判断P32按钮是否按下
        {
                Delay20ms();                                                        //延时20ms消抖
                if( P33 == 0 )
                {
                        state = !state;                                                //变量取反 0 1 0 1 0 1
                        P22 = 0;
                        printf(&quot;state:%d\r\n&quot;,(int)state);

                        while( P33 == 0 );                                        //等待P32松开

                }
        }

        //课后任务2
        if(P32 == 0)                                                                //判断P32按钮是否按下
        {
                Delay20ms();                                                        //延时20ms消抖
                if( P32 == 0 )
                {
                        state++;                                                //变量取反 0 1 0 1 0 1
                        //P22 = 1;
                        printf(&quot;state:%d\r\n&quot;,(int)state);
                        if(state == 1){
                                P20 = 0;
                        }else if(state == 2){
                          P21 = 0;
                        }else if(state == 3){
                                P22 = 0;
                        }else if(state == 4){
                                P23 = 0;
                        }else if(state == 5){
                                P24 = 0;
                        }else if(state == 6){
                                P25 = 0;
                        }else if(state == 7){
                                P26 = 0;
                        }else if(state == 8){
                                P27 = 0;
</code></pre>

macrofei 发表于 2024-12-16 14:16:13

<p>第七集 定时器中断<br />
了解了定时器的执行过程<br />
配置定时器:设置定时器的工作模式、初值、是否启用中断等。<br />
启动定时器:通过设置控制寄存器启动定时器,开始计数。<br />
溢出与中断:定时器溢出后触发中断,执行预定的中断服务程序。<br />
停止定时器:完成任务后,停止定时器的计数。</p>
<p>函数的声明和调用</p>
<p>#include &quot;AI8051U.h&quot; //调用头文件<br />
#include &quot;stc32_stc8_usb.h&quot; //调用头文件<br />
#include &quot;intrins.h&quot; //d调用头文件</p>
<p>#define u8 unsigned char //8位无符号变量(0-255)<br />
#define u16 unsigned int //16位无符号变量(0-65535)</p>
<p>u8 state = 0; //初始状态<br />
u8 Run_State = 0; //运行状态<br />
u8 num = 0; //初始状态<br />
char *USER_DEVICEDESC = NULL;<br />
char *USER_PRODUCTDESC = NULL;<br />
char *USER_STCISPCMD = &quot;@STCISP#&quot;;<br />
void Delay20ms(void) //@24.000MHz Delay20ms();<br />
{<br />
unsigned long edata i;</p>
<pre><code class="language-html">_nop_();
_nop_();
i = 119998UL;
while (i) i--;

</code></pre>
<p>}<br />
void Timer0_Init(void); //3秒@24.000MHz //函数声明<br />
void Timer1_Init(void); //3秒@24.000MHz //函数声明</p>
<p>void main(void)<br />
{<br />
int count=1; //按键计数变量</p>
<pre><code class="language-html">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中断
Timer0_Init();                                                                        //定时器初始化
Timer1_Init();
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 )
                {
                        if(state == 0){
                                num+=2;
                                printf(&quot;功d+2 当前功d:%d &quot;,num);
                                P20=0;
                                Timer1_Init();
                        }else{
                                num+=1;
                                printf(&quot;功d+1 当前功d:%d &quot;,num);
                                P21=0;
                                Timer0_Init();
                        }
       
                        while( P32 == 0 );                                        //等待P32松开
       
                }
        }
        if( P33 == 0 )                                                                //判断P32按钮是否按下
        {
                Delay20ms();                                                        //延时20ms消抖
                if( P33 == 0 )
                {
                        if(state==0){
                                printf(&quot;单倍功d时间&quot;);
                                state = 1;
                        }else {
                                printf(&quot;双倍功d时间&quot;);
                                state = 0;
                        }
                        while( P33 == 0 );                                        //等待P32松开
       
                }
        }
}

</code></pre>
<p>}</p>
<p>void Timer0_Isr(void) interrupt 1<br />
{<br />
P21=1;<br />
TR0=0;<br />
}</p>
<p>void Timer0_Init(void) //1秒@24.000MHz<br />
{<br />
TM0PS = 0x1E; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )<br />
AUXR &amp;= 0x7F; //定时器时钟12T模式<br />
TMOD &amp;= 0xF0; //设置定时器模式<br />
TL0 = 0xFC; //设置定时初始值<br />
TH0 = 0x03; //设置定时初始值<br />
TF0 = 0; //清除TF0标志<br />
TR0 = 1; //定时器0开始计时<br />
ET0 = 1; //使能定时器0中断<br />
}<br />
void Timer1_Isr(void) interrupt 3<br />
{<br />
P20=1;<br />
TR1 = 0;<br />
}</p>
<p>void Timer1_Init(void) //2秒@24.000MHz<br />
{<br />
TM1PS = 0x3D; //设置定时器时钟预分频 ( 注意:并非所有系列都有此寄存器,详情请查看数据手册 )<br />
AUXR &amp;= 0xBF; //定时器时钟12T模式<br />
TMOD &amp;= 0x0F; //设置定时器模式<br />
TL1 = 0xFC; //设置定时初始值<br />
TH1 = 0x03; //设置定时初始值<br />
TF1 = 0; //清除TF1标志<br />
TR1 = 1; //定时器1开始计时<br />
ET1 = 1; //使能定时器1中断<br />
}</p>
页: [1]
查看完整版本: AI8051U实验箱学习记录