海底的龙 发表于 2024-12-15 13:38:15

<p><img src="data/attachment/forum/202412/15/133742lldlzzna3af3o374.jpg" alt="bf0d7e119be58d873007c8dd2d1f4c6d_origin1.jpg" title="bf0d7e119be58d873007c8dd2d1f4c6d_origin(1).jpg" />果然有效试验箱已经到了<img alt="ciya" class="emoji" src="https://www.stcaimcu.com/static/image/smiley/default/ciya.gif" title="ciya" /></p>

pmnurylk 发表于 2024-12-15 20:25:54

催更!

摸鱼小刘 发表于 2024-12-15 21:07:18

<p>打卡第四天</p>

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

<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>
<li>总结与注意事项<br />
确保I/O口配置正确,避免电路短路或配置错误。<br />
使用双引号包含自己的头文件,避免缺少文件的问题。<br />
注意电路连接和电流限制,保护LED和单片机的安全。</li>
</ol>
<p><img src="data/attachment/forum/202412/16/004322wtvs3vkkticsokos.jpg" alt="69b24bcb18beb3d354208db46b920b7.jpg" title="69b24bcb18beb3d354208db46b920b7.jpg" /></p>
<p><img src="data/attachment/forum/202412/16/004334ymyy24y4e14ro2yv.png" alt="image.png" title="image.png" /></p>

macrofei 发表于 2024-12-16 02:01:27

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

macrofei 发表于 2024-12-16 02:53:15

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

macrofei 发表于 2024-12-16 03:48:25

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

macrofei 发表于 2024-12-16 04:26:03

<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 u8unsigned 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.000MHzDelay20ms();<br />
{<br />
unsigned long edata i;</p>
<pre><code>_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>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>

13563601531 发表于 2024-12-16 09:45:46

<p>看了第八集 定时器的周期任务调度 才知道定时器还可以这么用 ,有学了一招</p>

LXXboss 发表于 2024-12-16 10:13:50

下载软件问题:下载程序时提示未知芯片或下载失败,可能是下载软件版本不兼容。需确保使用与实验箱匹配的最新版下载软件,如AIapp-ISP软件,可到官方网站下载最新版本。
- 编译错误:在使用Keil等编译软件时,可能会出现编译错误,如变量未定义、语法错误等。需要仔细检查程序代码,根据编译提示信息查找并修改错误,确保代码书写规范、变量定义正确。
- 仿真调试问题:仿真调试时无法跟踪显示局部和行参变量,可尝试在程序中使用全局变量来变通查看相关数据;如果问题依旧存在,可能是驱动调试的插件程序存在问题。

硬件与软件配合问题

- 程序不运行或运行异常:程序下载成功后,但实验箱上的设备无反应或运行结果与预期不符。首先检查程序中对硬件的配置是否正确,如IO口的初始化、引脚功能设置等;然后检查硬件连接是否正确,是否存在短路、断路等问题;还可以通过单步调试或添加调试信息来查找程序中的逻辑错误。
- 显示问题:显示屏无法正常显示或显示异常,可能是显示屏与实验箱不兼容或配置错误。需确保使用与实验箱匹配的显示屏,如3.3V供电的显示屏;检查显示屏的引脚连接是否正确,是否需要进行特殊的配置或初始化操作。
页: 20 21 22 23 24 25 26 27 28 29 [30] 31 32 33 34 35 36 37 38 39
查看完整版本: 《8051U深度入门到32位51大型实战视频》,【免费 + 包邮 送】实验箱@Ai8051U,100万套