272761180 发表于 2024-11-25 09:53:39

示例贴:日日自新学习AI8051U


君子知命不惑,日日自新。

本人为电子爱好者,2024年6月入坑,在嘉立创陆续参加了 ESP32、STM32F4等几个活动,对嵌入式开发有了一定程度了解。11月通过嘉立创AI8051U活动接触到STC新发布的这款MCU,这也是本人第一次接触到这款芯片。

目前已申请到官方赠送的芯片,设计制作了一款48封装的开发板和一块兼容40和48封装的拓展学习板,再加上手头现有的模块可以开始学习了。

上半月把冲哥的STC32视频教程学习了7788,基本上了解上手了stc32和AI8051的基本功能。趁着AI8051U芯片视频教学的陆续发布,在此新开个板块深入了解这款芯片的不同寻常之处。

学习笔记在此板块下陆续更新,不定期放出实战联系源码。

后续考虑会在其它板块开源自己设计的开发板和拓展板。



20241127更新:学习笔记仅为个人理解,写出来的目的就是为了让各位大佬批评指正、加深理解。理解错误的地方我也不会修订更正(会继续留言指出),需要同学们下翻查找大佬的更正留言,不要偏信哦!

272761180 发表于 2024-11-25 10:51:09

【第一课】《序言》

AI8051U强在哪里?

一、优化了QSPI的FLASH读写能力
    案例展示使用8080的8位并口屏演示事例,手写的刷频率较高;可以用来驱动LED屏幕作为交互使用,同时对大容量视频的播放有了质的提升。
    新增的QSPI功能:即四线串行外设接口,是一种高速的、面向Flash存储器的串行接口标准。相比于传统的SPI,QSPI接口通过增加数据线的数量(从SPI的一条数据线增加到QSPI的四条数据线),实现了更高的数据传输速率和更大的吞吐量。这使得QSPI接口特别适合于需要高速访问大量数据的嵌入式系统。



二、 支持I2S录音放音功能
    视频展示了录放音功能,因为没讲原理所以不太清楚厉害在哪。所以查阅原理图、代码和手册进行分析。
    没有玩过音响,对这一块不太了解。看了一下原理图,录音功能主要是MIC后面接了低通滤波和运放后再接ADC功能(?),播放功能主要是TLV320AIC23芯片,借助其集成的ADC和DAC功能接MCU的I2S。软件源码方面,初步了解到采样后数据存储在FLASH中,播放时从FLASH读取数据通过I2S发送给芯片。对录音时的采样部分还要继续学习。



三、 PWM可以兼容DMA了,四、可以进行硬件浮点乘除单元计算,用于制作频谱分析仪
    视频通过上位机实现了频谱仪功能。这里查阅手册发现,对比STC32G和AI8051U,在DMA方面的提升可不只是一点点:
    在PWM/QPI/TFT LCD/方面加入了DMA支持,同时还支持P2P即外设到外设的数据传输,释放CPU算力(就好像老板雇了个工作能力超强的秘书)。



五、支持部署一些AI计算模型,比如手写计算器,也就是芯片名称AI的由来(硬件乘除,单精度浮点)
    这个网友的案例在活动群里早有了解。手写识别涉及到最基本的AI学习。经前期了解,这种功能大致实现思路是,通过构建一个适合与手写数字识别的神经网络算法模型,在电脑端导入训练素材并经过多次迭代计算后,将神经元输出结果限制在较为合理的误差范围内,得出变量的参数;然后将该算法部署在AI8051U当中进行实时计算。
    这个案例说明了这款芯片的算力是支持一些AI算法的。

除此之外,该芯片设计兼容了以往部分芯片的引脚等,同时在我前期制作开发板的过程中发现,这款MCU的最小外围电路极少,简直跟差点就能用没啥区别。

272761180 发表于 2024-11-26 10:20:36

本帖最后由 272761180 于 2024-11-27 10:22 编辑

第二课 《硬件及工具介绍》

本节课讲解了我垂涎已久{:5_289:}的AI8051U试验箱的功能和模块。试验箱照片看着挺大但是视频来看挺小巧的。各模块功能不再赘述,直接上图:



这节课虽然只是介绍官方产品,但是也不是说没学习到东西,我用自己制作的开发拓展板和官方的进行了比对,主要研究学习了一下我没有掌握的模块功能。先抛砖引玉把我的板子展示一下:




考虑到我经常更换开发环境,要求便携性和可拓展性,所以做成了分体的小型开发板和较大的拓展板,同时拓展板各功能模块采用插接形式连接,提高灵活度,也方便外出开发时随身携带某一模块。对比官方开发板来看,我的主要是集中于各个独立的功能模块相互配合,而官方的更具有系统性,比如音频模块、示波器模块更具有实战意义,PSRAM和QSPIFLASH能够配合其他功能实现DMA的P2P功能,更能够展示AI8051U的核心竞争力,也更能够玩出花样。现在才明白为什么我跟着STC视频学习并实战完了自己的开发板后,仍然没有感受到它的优势之处了。下面总结一下本节课学习到的内容:

一、扩展了32K的PSRAM

使用74HC573配合IS62C256拓展了32K外部并行总线。个人理解当数据从总线传输到SRAM时,先通过74HC573进行锁存,然后再写入SRAM,这样在提高传输速度的同时(是否使用DMA的P2P传输扩展片内RAM?)可以确保数据的准确性和完整性,后面实战课程再验证想法。(这一部分我理解有误,已有大佬指出)




二、音频输入输出

音频输入使用的是运放+滤波器电路,配合外部麦克完成DAC转化,再由单片机ADC-DMA采样。音频输出功能使用了TI公司的TLV320AIC23立体声音频编解码器芯片,内置耳机输出放大器,支持可编程的ADC和DAC,但是电路没有使用这个芯片作为声音输入(悬空了麦克输入的MCIIN和MICBIAS引脚以及LINE IN 的左声道L和R引脚),不知道为啥。




三、SPI FLASH 、TF储存

使用W25Q80串行FLASH芯片以及QSPI通讯,或者是SPI协议的TF卡座。这里有个疑问,TF卡座的P2.4/P2.5/P2.6三条共用信号线是与PSRAM重复了(A12/A13/A14),而FLASH芯片使用的是P4+引脚,但是这里为什么原理图上解释说是和FLASH共用呢?




四、示波器电路

电压调理部分(负压产生)的SGM3204芯片(支持2-5.5V和最大200mA负载)输出-3.3V;
波形采集部分包含跳线帽和电压组成的信号衰减电路(降压)、TP2604S运放和74HC4051组成的数控增益运放电路,最后接入ADC引脚实现采集;
波形发生部分由PWM模拟DAC输出正弦波后经过TP2604S运放输出。

我之前自学使用STM32F407制作了一个DIY示波器,这个电路对我原来的电路有很大的改进参考意义,比如SGM3204芯片、数控增益灯带。同时,实验箱的示波器功能主要是串口通信实现可视化(看的案例),这里考虑是否能用显示屏+DMA的P2P技术做成一个自展示的示波器。另外,我之所以选择STM32F4是因为它出色的DAC功能,而AI8051U使用PWM当做DAC输出信号,具体情况是否理想,以及运算的电路设计计算,待后面学习实战时再研究。




最后,原理图使用了多个74HC系列集成电路芯片(74HC4051高速CMOS器件、74HC573透明锁存器、74HC595高速移位寄存器)。74HC4051主要用于模拟信号的多路选择和分配;74HC573则作为透明锁存器,在缓冲寄存器、I/O通道等场合发挥重要作用;而74HC595则以其串行输入、并行输出的特性,在节省单片机IO口、实现数据转换等方面具有广泛应用。
我从来没用过,后面会深入研究学习,有了解的大佬也可以指导我一下。

总之,经过试验箱的原理图学习和我DIY的开发板对比,我发现自己制作的开发板受限无法全部实战上面的一些功能。但是,得益于我的开发板的可拓展性,下阶段在继续学习的基础上计划再制作出几个拓展模块来。

272761180 发表于 2024-11-26 11:38:55

本帖最后由 272761180 于 2024-11-27 10:25 编辑

【第三课】 《点亮第一颗LED》

实战小白化身点灯大师上线!(不是,其实基础功能已经学完一遍了)本节课主要讲了两部分重点内容,其一是工程的搭建,其二是IO点灯。

一、环境搭建

这里不再赘述,相比于使用vscode部署esp idf开发环境那个“难”以置信的方法,AI8051U环境搭建很为方便,技术手册里面也是手把手地教导。下面讲几个注意点:

1. AI8051U支持32位和8位两种方式,由不同编译器支持,注意区分,烧录时ISP也要注意选择;



2. 安装好编译环境后注意看一下软件的激活情况,没有激活时当项目工程体量较大会无法编译。这里官方没有讲到,因为要涉及到魔法激活的事情。激活后会有激活号。
未激活时报错如下:*** ERROR L250: CODE SIZE LIMIT IN RESTRICTED VERSION EXCEEDED
                           LIMIT:   0800H BYTES



二、IO点灯

很简单粗暴的一行代码实现: PXX=0(下拉)、PXX=1(上拉)。

因为我有强迫症,为了增加代码可读性,进行了封装:(这一部分代码是错误的,8051的运行逻辑不能照搬STM32,不用封装为宜,已有大佬指出)
// 为P5端口封装设置引脚状态的函数
void set_P5(unsigned char pin, unsigned char level) {
   if(pin>=0 && pin <=7){
                        if (level == HIGH) {      P5 |= (1 << pin);      }
                        else {      P5 &= ~(1 << pin);      }
                }
}
void BoardLED_ON(void)      //      开发板板载绿色LED      P50
{
      set_P5(0,LOW);                //P50写入低电平开启LED
}
void BoardLED_OFF(void)
{
      set_P5(0,HIGH);                        
}

下面给出一些拓展:

1. IO口模式

不同IO口有不同功能,技术手册也都解释说明了。这里板子启动时默认将所有IO口都设置为了准双向口。
准双向口的拉电流能力是270-150uA,因此也可以驱动高亮0603LED而不需要限流电阻。
但是,推挽输出的拉电流能力能够到20mA,会达到某些0603LED的Imax,因此需要电路串联限流电阻。当然,推挽输出模式下LED发光会更亮。

P5M0 = 0x01;               //推挽输出模式开灯
      P5M1 = 0x00;               //注释掉这两行为准双向口模式开灯



图左为准双向口,图右为推挽输出模式。那么为什么两个图的灯亮度一致呢?(这一部分是需要IO口拉高点灯时,准双向口和推挽才会有明显的差异,我这里因为使用限流电阻所以看不出来,已有大佬指出)
因为虽然推挽模式下约为uA级别电流,而当使用推完输出模式在3.3V供电模式下,由于电路串联了1K的限流电阻,电流 I=(3.3-Vf)/1000。翠绿色LED的Vf在3V左右,因此电路电流约为3mA(这一部分实际是0.3mA,已有大佬指出)。开发板使用的是高亮LED,因此流明差别肉眼辨认不出。因为现在是在外实验的,没有使用我的大开发板;大板上面可以使用三色灯进行进一步测试。

2. 关于Borad_Init()

另外,刚开始写代码看到案例的时候会有读者质疑下面这一串是什么东西了吧,这里做个解释:
P_SW2 = 0X80;                //使能访问XFR,没有冲突不用关闭
      CKCON = 0x00,                //设置外部数据总线速度为最快
      WTST= 0x00;                //设置程序代码等待参数
                                                                        //赋值为0可将CPU执行程序的速度设置为最快
      
      P0M0 = 0x00; P0M1 = 0x00;
      P1M0 = 0x00; P1M1 = 0x00;
      P2M0 = 0x00; P2M1 = 0x00;
      P3M0 = 0x00; P3M1 = 0x00;
      P4M0 = 0x00; P4M1 = 0x00;
      P5M0 = 0x00; P5M1 = 0x00;

那么这就完了吗?并不是的。


每款MCU工作时都要进行时钟配置,那么为什么没有看到AI8051U像STM一样进行SYSCLK配置呢?其实,当你打开ISP进行烧录的那一刻,你已经配置完了。(WOWOOOOOOOOOOOO!)



也就是说,AI8051U的时钟配置更为灵活,无需进行代码配置,只要在使用时钟进行相应计算时做个宏定义#FOSC 即可。这里可以阅读我的其他帖子,有大佬解释的很到位:
新手请教关于AI8051U的时钟问题https://www.stcaimcu.com/forum.php?mod=viewthread&tid=12083(出处: 国芯技术交流网站)

另外,代码里也并不是不用配置时钟,毕竟时钟源也是需要MCU选择的,只是系统默认使用高速内部IRC,帮你省掉了下面的代码:

//注:芯片上电后系统会默启动内部高速HRC,并选择为系统时钟,
      //所以一般情况下不需要作这一部分设置
//      HIRCCR = 0X80;                                                //启动内部高速IRC
//      while (!(HIRCCR & 1));                //等待时钟稳定,检查最低位ST状态,为1时震荡频率稳定
//      CLKSEL = 0x00;
这里再提到一句,ISP可设置的IRC频率范围应该是通过高速内部IRC计算的,即



为什么±27%?是时钟误差大吗?当然不是的,是可调的IRC范围,也就是类似11.0592等数据的来源。因此在自己设置时钟时,注意不要设置到盲区了
(大佬指导一下是这个意思吗)

最后,如果是使用片外晶振,配置代码如下(手册也已给出)

//选择时钟来源为内部低速IRC
//      IRC32KCR = 0X80;                                        //启动内部低速IRC
//      while (!(IRC32KCR & 1));
//      CLKDIV = 0X00;
//      CLKSEL = 0x03;

      //选择时钟来源为内部48M IRC
//                IRC48MCR = 0X80;                                        //启动内部48M IRC
//                while (!(IRC48MCR & 1));
//                CLKDIV = 0X02;
//                CLKSEL = 0x0C;
                        
      
      //选择时钟来源为外部32K晶振                【板载这个】
//      X32KCR = 0xC0;                                                      //启动外部晶振
//      while (!(X32KCR & 1));                        //等待时钟稳定
//      CLKDIV = 0X00;
//      CLKSEL = 0x02;                                                      //选择外部32K晶振

      //选择时钟来源为外部晶振
//      XOSCCR = 0xC0;                                                      //启动外部晶振
//      while (!(XOSCCR & 1));
//      CLKDIV = 0X00;
//      CLKSEL = 0X01;                                                      //选择外部晶振      
同样,如果使用外部晶振,要研究一下芯片的上电过程了:


配置后,按照时钟树配置相应变量分频、倍频就行了。(还没试验验证操作性)

这堂课涉及内容很少吗?其实不是的。
点灯大师很低级吗?其实不是的。



272761180 发表于 2024-11-26 11:48:09

点灯源码和视频奉上



272761180 发表于 2024-11-26 17:16:46

【第四集】 《USB不停电下载》


接上一堂课拓展的有关芯片上电流程的话题,这节课讲了几种下载方式。从芯片最小电路得知,使用USB插头单刀直入地接入D+和D-就能实现电路下载。



而开发手册也贴心地分5V供电和3.3V供电,手动烧录、全自动单串口和双串口,几种模式分门别类地精讲了每类下载烧录方式的电路图和操作方法。下面简要总结一下:

一、USB手动下载

该方式会占用一个IO口,导致该IO口仅能用于特定的烧录功能,同时必须要设计电子开关或者机械自锁开关用于MCU-VCC的上电、停电操作。

方法一:P3.2接地借助INT0中断再结合电源开关。
方法二:使用P4.7nRST的复位功能,免通断电案件烧录。

这里强调一点,那就是无论是方法一还是方法二,只要设计了手动下载方式,就必须要设计一个MCU供电的硬件开关。仅仅使用USB口插拔的通断电是不行的,因为从芯片的上电过程可以了解到,MCU启动初期会进入系统ISP监控程序,此时会依据USB的电路情况判断是进入ISP下载模式还是直接进入用户程序区,这就要求这一时刻的状态应该是USB口先于MCU通电。当使用USB插拔通断时,芯片和USB是同时上电的,芯片会因为没有检测到USB电路判断为不需要进入ISP下载模式,从而直接进入用户程序区。这也是硬件设计需要注意的部分。



有同学会有疑问,方法二不是免通断电吗,那为什么还要设计一个开关呢?

这是因为,P4.7的复位功能需要芯片第一次上电后配置。该引脚默认配置模式为IO功能,需要先烧录一次并在ISP选择取消P4.7用作IO功能而使用复位功能。那么,如果不设计手动开关,就没办法进行这一次烧录,也就没有后面的 先有鸡还是先有蛋 的话题了。想省元器件的同学我这里提供一个思路,那就是把开关位置替代为两个测试点,首次使用时镊子短接停供电,然后再使用方法二。



二、USB自动下载


当然,论懒是永远没有官方懒的,为了图省事,官方干脆开发个USB自动烧录功能,这下不光省了串口芯片,连IO占用都免了。USB下载目前分两种方式,即USB-CDC方式和USB-HID方式。


以USB-CDC为例,执行烧录程序时有USB_INIT()函数,这里对库函数进行简要阅读,发现在配置好USB时钟、使能USB功能和中断后,在中断函数中读取了寄存器的值(有可能ISP的CMD命令就是存在这里),通过比较接受命令char *USER_STCISPCMD = "@STCISP#"值后执行数据接收等工作。(具体没细看,欢迎补充指正)


对于用户端而言,只需要在官网下载LIB并进行相关烧录后配置即可,当然这个烧录指令也是可以自定义的,只要ISP端和代码端一致即可。

三、串口自动下载


除了本节课讲的USB烧录方式,因为我在硬件开发过程中使用了Ai8H2K12U-SOP8芯片进行单串口自动烧录,而这个烧录芯片市场价0.95元,外围电路极少,买来自带烧录代码直接上手使用。甚至还有1元不到的SOP16封装的双串口芯片,在技术手册里同样进行了详细说明,按照电路图绘制后插电即可烧录,比CH340省钱省事多了。



附上我的串口电路



当然想学习体验手动和自动烧录的同学,可以使用下面的电路:


VCC 发表于 2024-11-27 03:06:24

272761180 发表于 2024-11-26 11:38
【第三课】 《点亮第一颗LED》

实战小白化身点灯大师上线!(不是,其实基础功能已经学完一遍了)本节课主 ...你提到:

图左为准双向口,图右为推挽输出模式。那么为什么两个图的灯亮度一致呢?
因为虽然推挽模式下约为uA级别电流,而当使用推完输出模式在3.3V供电模式下,由于电路串联了1K的限流电阻,电流 I=(3.3-Vf)/1000。翠绿色LED的Vf在3V左右,因此电路电流约为3mA。开发板使用的是高亮LED,因此流明差别肉眼辨认不出。因为现在是在外实验的,没有使用我的大开发板;大板上面焊接了插件LED,这个实验差别在家里会有质的提升。

这是因为你用的是低电平亮灯的接线方式。

准双向模式和推挽输出模式,在输出低电平的时候,工作状态是完全相同的。

VCC 发表于 2024-11-27 03:14:55

272761180 发表于 2024-11-26 11:38
【第三课】 《点亮第一颗LED》

实战小白化身点灯大师上线!(不是,其实基础功能已经学完一遍了)本节课主 ...

电流 I=(3.3-Vf)/1000。翠绿色LED的Vf在3V左右,因此电路电流约为3mA。

你计算错了哦,这时的电流是300uA吧{:5_278:}

VCC 发表于 2024-11-27 03:22:11

本帖最后由 VCC 于 2024-11-27 04:10 编辑

272761180 发表于 2024-11-26 10:20
第二课 《硬件及工具介绍》

本节课讲解了我垂涎已久的AI8051U试验箱的功能和模块。试验箱照片看着挺大但是 ...
使用74HC573配合IS62C256拓展了32K外部并行总线。个人理解当数据从总线传输到SRAM时,先通过74HC573进行锁存,然后再写入SRAM,这样在提高传输速度的同时(是否使用DMA的P2P传输扩展片内RAM?)可以确保数据的准确性和完整性,后面实战课程再验证想法。
你的理解是错的。


通过原理图不难看出,这个RAM芯片的A0~A7以及D0~D7复用了单片机的P00~P07口(其余地址线A8~A14是专用的,用了P20~P26口)
这个锁存器起到了复用IO的作用。使得P00~P07口同时充当了8位地址线和8位数据线,节省了IO

但是,从实践的角度,另一个答案是:
Ai8051U要求必须这样接线!

这是在EXTRAM寄存器置1后,单片机会自动进行的操作

具体用到的是引脚的这些复用:

其中可以看到,P0口标记为AD0~AD7。意为地址A0~A7和数据D0~D7复用
(说句题外话,前些日子看见有群友误以为这个AD是ADC输入通道的意思,因此将板子设计错了{:4_167:})

51单片机的这个功能从英特尔的祖师爷芯片上就一直有。当年的文档也要求使用一个锁存器芯片(图中的LATCH)




这款RAM芯片的功能框图


另附数据手册:






VCC 发表于 2024-11-27 03:40:41

本帖最后由 VCC 于 2024-11-27 03:44 编辑

272761180 发表于 2024-11-26 11:38
【第三课】 《点亮第一颗LED》

实战小白化身点灯大师上线!(不是,其实基础功能已经学完一遍了)本节课主 ...
虽然你很有想法,但我还是要泼一盆冷水


因为我有强迫症,为了增加代码可读性,进行了封装:

[*]// 为P5端口封装设置引脚状态的函数
[*]void set_P5(unsigned char pin, unsigned char level) {
[*]   if(pin>=0 && pin <=7){
[*]                        if (level == HIGH) {      P5 |= (1 << pin);      }
[*]                        else {      P5 &= ~(1 << pin);      }
[*]                }
[*]}
[*]void BoardLED_ON(void)      //      开发板板载绿色LED      P50
[*]{
[*]      set_P5(0,LOW);                //P50写入低电平开启LED
[*]}
[*]void BoardLED_OFF(void)
[*]{
[*]      set_P5(0,HIGH);
[*]}
[*]

复制代码

你这个void set_P5(unsigned char pin, unsigned char level)函数的做法是非常不对的!甚至说是bug也不为过!

{:4_171:}
你这里对P5寄存器进行了一次读字节、位修改、回写字节的操作。
但是,如果P5工作在准双向模式下,读到的内容是IO的输入缓冲器检测到的电平,并不一定是你上次写入的P5输出值。所以你这个操作可能会干扰到P5端口上其他有外部输入的IO口的状态。

举个例子

如果P5端口的准双向输出状态是 00000011
而P51被外部的某个传感器拉低了

那么准双向输入状态就是 00000001

此时调用该函数,尝试将P50置为低电平

那么准双向输出状态将会可怕地成为 00000000

意味着你的代码将其他IO口误操作了!!!

STC的51单片机不支持像你以前玩STM32一样操作,因为它的IO输入、IO输出寄存器是独立的,互相不会有干扰。
下图摘自STM32F103参考手册 RM0008最新版




而STC 51单片机的IO输入输出寄存器是共用的!(摘自Ai8051U数据手册)

而优点呢?这些寄存器都是支持位操作的(地址的二进制位低3位是0的寄存器,都支持位寻址,比如80h、A8h、B0h)
如下图


切记不要再这样写了!!!这是画蛇添足的错误做法。

在每一个平台都有每个平台自己的架构和玩法。比如STM32 MCU平台,8051平台。尤其是涉及底层操作的时候!必须要熟练了解其中的细节,才能避免出错

至于正确的写法?
我建议,这就是最好的了。没必要做其他复杂的函数封装。
void BoardLED_ON(void)      //      开发板板载绿色LED      P50
{
   P50=0;                //P50写入低电平开启LED
}
void BoardLED_OFF(void)
{
   P50=1;
}

页: [1] 2 3 4 5
查看完整版本: 示例贴:日日自新学习AI8051U