打印
[PIC®/AVR®/dsPIC®产品]

【CuriosityNano测评报告】与 AVR 的第一次相遇

[复制链接]
2927|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wziyi|  楼主 | 2021-3-20 23:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 wziyi 于 2021-4-17 15:50 编辑

最近有幸获得一块 AVR128DB48 Curiosity Nano 板板,虽然 2020 年初就放出狠话,全面转入 32 位单片机阵营,不再研究 8 位单片机。看到这娇俏可人小可爱,忍不住打了老脸。没事,反正又不是第一次了,习惯了。在 8 位单片机中,只用过两种,除了众所周知的 STC89C51 外就是 PIC 了。其中对 PIC 的研究了一年之久,对它的小兄弟 AVR 只听说过。


总是提示含有不良信息,发布不了。没办法只能放在知乎上了,平时工作忙,只能在夜晚玩玩。打算把自己对单片机的心得啥子全写进去,篇幅有点大。。。


使用特权

评论回复
评论
251566208 2021-4-1 11:26 回复TA
哈哈哈,那就继续用PIC的吧 
沙发
wziyi|  楼主 | 2021-3-20 23:05 | 只看该作者
本帖最后由 wziyi 于 2021-5-24 22:34 编辑

与 AVR 的第一次相遇 https://zhuanlan.zhihu.com/p/358439390

与 AVR 的第一次相遇(二)https://zhuanlan.zhihu.com/p/360501334

与 AVR 的第一次相遇(三) https://zhuanlan.zhihu.com/p/365817835

与 AVR 的第一次相遇(四)https://zhuanlan.zhihu.com/p/374941860

使用特权

评论回复
板凳
jazzyfox| | 2021-3-21 19:52 | 只看该作者
AVR是做大死的范例之一,中间的例子是NXP,现在的例子是STM,原来出货量那叫一个大,现在就呵呵了

使用特权

评论回复
地板
coody| | 2021-3-21 21:36 | 只看该作者
与AVR第一次相遇忘记了,但是跟AVR分手倒是很记得,2009年AVR供货门之后,再也没碰过AVR了。

使用特权

评论回复
5
coody| | 2021-3-21 21:38 | 只看该作者
jazzyfox 发表于 2021-3-21 19:52
AVR是做大死的范例之一,中间的例子是NXP,现在的例子是STM,原来出货量那叫一个大,现在就呵呵了 ...

确实,AVR、NXP作死我是经历了,现在难道真的是ATM32了?希望这次问题之后,国人多点用国产的8位、32位机。

使用特权

评论回复
6
wziyi|  楼主 | 2021-3-23 17:49 | 只看该作者
都是大佬,那时候我还在上小学呢

使用特权

评论回复
7
99288697| | 2021-3-24 07:00 | 只看该作者
coody 发表于 2021-3-21 21:36
与AVR第一次相遇忘记了,但是跟AVR分手倒是很记得,2009年AVR供货门之后,再也没碰过AVR了。 ...

Microchip收购后是不是就不缺货了?

使用特权

评论回复
8
晓伍| | 2021-4-2 16:45 | 只看该作者
什么叫不良信息啊

使用特权

评论回复
9
八层楼| | 2021-4-2 16:46 | 只看该作者
希望楼主调试顺利

使用特权

评论回复
10
观海| | 2021-4-2 16:48 | 只看该作者
起点是不是有点难啊

使用特权

评论回复
11
木木guainv| | 2021-4-2 16:49 | 只看该作者
avr和arm有什么不同啊

使用特权

评论回复
评论
wziyi 2021-4-17 16:50 回复TA
avr 里面也有32位的 arm 核的单片机,这次说到是 8 位单片机,内核是 avr 自研的 
12
guanjiaer| | 2021-4-2 16:51 | 只看该作者
不知道需要屏蔽的关键字是什么

使用特权

评论回复
13
heimaojingzhang| | 2021-4-2 16:52 | 只看该作者
用的多了就习惯了

使用特权

评论回复
14
wziyi|  楼主 | 2021-4-17 16:50 | 只看该作者
guanjiaer 发表于 2021-4-2 16:51
不知道需要屏蔽的关键字是什么

我也不知道,在其它平台就没啥问题

使用特权

评论回复
15
wziyi|  楼主 | 2021-4-17 16:51 | 只看该作者
观海 发表于 2021-4-2 16:48
起点是不是有点难啊

有基础就没啥难度,小白可能呢的花点时间

使用特权

评论回复
16
zhengshuai888| | 2021-4-18 15:09 | 只看该作者
楼主第一次用AVR啊。现在都很少人用这个了。

使用特权

评论回复
17
wziyi|  楼主 | 2021-4-18 17:18 | 只看该作者
本帖最后由 wziyi 于 2021-4-18 17:28 编辑

接下就是所有单片机都有的也是最简单的外设了,就是那个亮灯用的 GPIO 。从数据手册看出比较有意思的特性是带有输入电平翻转的功能、和 GPIO 寄存器内存地址映射。尤其是后者,第一次见到。至于其它功能都是常规操作了。
小白要留心这个小提示,可以先把所有引脚都统一配置为模拟模式,之后用到哪个引脚再对其重新配置,这样有利于降低整机功耗。
啥也不说了先亮个灯吧。这是必须得看硬件设计文档了,最好是看原理图了,不过既然官方画了这么好看的示意图,暂时以示意图为主。从图中看出 PORTC 端口基本没有做引脚复用,本着不浪费的原则,就用它点灯了。
一般来说,从功能构思,元件选型,电路设计到 PCB Layout ,最好焊接成型整个周期是以周来计算的。2020 年至 2021 年芯片采购变得极为困难,无疑会导致硬件制造流程变得更加漫长。单片机代码涉及的很多电路上的信息交互,传统的开发调试一般是等硬件电路制造完成后,在硬件电路上仿真调试。随着嵌入式软件开发技术的进步,可以对单片机代码采用全虚拟仿真和半实物仿真,这样就不要苦等硬件电路了。
数据手册动辄上百页,但我们只想用 GPIO 输出个高低电平。GPIO 章节的介绍可以慢慢瞅,现在要蹦到寄存器描述环节。里面有很多个相关寄存器,需要配置就 2 个而已。第一个是控制引脚数据方向的寄存器 DIR,要对外输出就得把 DIR 置 1。
第二个关键寄存器 OUT 就是控制输出值的高低。OUT 置 1 就是输出高电平,OUT 置 0 就是输出低电平。
现在又可以直接甩代码了。因为单片机一旦执行晚所有代码就会自动复位,因此 main 函数的最后得放置一个 while 循环防止单片机复位。会闪动的灯光才好看呀,所以得写有专门实现延时效果的 delay 函数。它就是让单片机做点无用功,好比小明走的太快了需要给她加点负重,让她走慢点。大家可以看到 delay 函数就是三个 for 循环。这里得补充个知识,此时 char 默认是有符号的字符型,但是这个不是通用的,有的嵌入式单片机编译器, char 默认是无符号的字符型。在 XC8 for AVR 里面可以通过修改编译器参数来 char 的默认类型。这个知识对小白来说可能有点深了。这个会影响 for 循环里 x,y,z 的最大值,不得不讲一下。在很多教程中,会用 #define 来 unsigned char 改为 uchar。因为宏定义不便于小白阅读和调试,所以我的教程里会尽量避免使用这个东西。
#include <avr/io.h>
#include <avr/cpufunc.h>
FUSES = {
        .WDTCFG = 0x00, // WDTCFG {PERIOD=OFF, WINDOW=OFF}
        .BODCFG = 0x00, // BODCFG {SLEEP=DISABLE, ACTIVE=DISABLE, SAMPFREQ=128Hz, LVL=BODLEVEL0}
        .OSCCFG = 0xF8, // OSCCFG {CLKSEL=OSCHF}
        .SYSCFG0 = 0xD2, // SYSCFG0 {EESAVE=CLEAR, RSTPINCFG=GPIO, CRCSEL=CRC16, CRCSRC=NOCRC}
        .SYSCFG1 = 0xE8, // SYSCFG1 {SUT=0MS, MVSYSCFG=DUAL}
        .CODESIZE = 0x00, // CODESIZE {CODESIZE=User range:  0x0 - 0xFF}
        .BOOTSIZE = 0x00, // BOOTSIZE {BOOTSIZE=User range:  0x0 - 0xFF}
};

LOCKBITS = 0x5CC5C55C; // {KEY=NOLOCK}

void clock(void);
void delay(char a);

int main(void){
    unsigned char i=0;
   
    clock();    //初始化时钟
   
    PORTC.DIR = 0xff;   //设置引脚为输出模式
    PORTC.OUT = 0xff;   //设置引脚为输出为 0
   
    while(1){   
        PORTC.OUT = i;  //不断改变引脚输出值
        i++;
        delay(100);     //适当延时方便后续观察
    }
    return 0;
}

void clock(void){
    CLKCTRL.MCLKCTRLA = 0x80;   //内部高速振荡器,时钟在对外输出
    CLKCTRL.MCLKCTRLB = 0x00;   //关闭预分频器分频
    CLKCTRL.OSCHFCTRLA = 0xbc;  //24MHz,一直开启,关闭时钟修正
}

void delay(char a){
    unsigned char x,y,z;
    for(x=0;x<a;x++){
        for(y=0;y<200;y++){
            for(z=0;z<200;z++);{
                _NOP();
            }
        }
    }           
}
我直接从 PORTC 端口里随便挑了 4 个 PIN 口观察电平变化。下图用的就是软件仿真方式观察效果,而非传统的开发板亮灯。
说到这了,得介绍下我们开发必备的软硬件工具了。IDE 是 MPLAB X ,编译器是 XC8 ,这个和其它单片机常用的 Keil 不太一样。 MPLAB X 和编译器是 XC8 是分开的,两者都可以从 Microchip 的官网上免费下载和使用。MPLAB X 自带有软件仿真器,不过最后和硬件联调时还得用到硬件仿真调试器。这方面的工具有很多,我用到是 PIC Kit4,市场价三百多吧。
它长这个样子的,基本上可以覆盖 Microchip 所有的单片机系列。价格与功能上与友商的 ST Link V3 旗鼓相当吧。一般官方的开发板上集成有板载调试器,可以不用单独购买 PIC Kit4 。平时自己设计电路就必须拥有一款硬件调试器,虽然可以通过串口来完成烧录程序,但是这种方式是不能进行调试的。
接着看代码,一般延时函数根据延时时间的长短而有所不同。最短的是指令级延时,_NOP(); 就代表延时一个指令的意思。想用这行代码必须添加头文件 #include<avr/cpufunc.h> 。然后就是毫秒级和微秒级延时了,这时根据系统时钟适当的控制 for 循环或者 while 循环的嵌套深度来实现。这时还得搞明白一个东西,那就是执行一条指令需要几个时钟。PIC 单片机里面,大约四十多条指令,基本上一条指令需要四个时钟。而 AVR 就不一样了,大约 一百三十多条指令,每条指令需要的时钟数也不太一样。关于指令的时钟数需要自己在数据手册慢慢扒拉,上面所讲仅作参考。下一步,就可以根据 C 语言代码脑补出它的汇编指令,再默算出循环执行时间。对小白来说,还有个笨办法,可以直接用示波器抓出波形,看代码运行时间。像下面这样,直接看下 PORTC 下任何一个引脚的电平变化周期即可看出 delay 的延时的数量级。
 while(1){    
        PORTC.OUT = 0x00;  //不断改变引脚输出值
        delay(1);          //适当延时方便后续观察
        PORTC.OUT = 0xff;
        delay(1);   
    }
其实很多 IDE 里面有专门的计算程序代码执行时间的功能,在 MPLAB X 里面叫做跑表,可惜的是这个功能这个功能暂时还不支持这个功能。不过,编译器是 XC8 的可以直接调用系统集成的延时函数,第一步当然是添加头文件 #include <avr/delay.h> ,然后调用即可。建议延时函数里面的参数不要超过 1000 。假如要做秒级延时,既可以简单粗暴地加大循环周期,也可以更高级点。可以让单片机休眠,时间到了再唤醒,这种方式有利于降低功耗,适合物联网设备的开发。这里暂且不讲怎么实现,留给后面章节。
while(1){    
        PORTC.OUT = 0x00;  //不断改变引脚输出值
        _delay_ms(1);      //适当延时方便后续观察
        PORTC.OUT = 0xff;
        _delay_us(100);     
    }
下面便是 PORTC 端口引脚输出电平仿真效果图,从仿真图上可以看出,延时函数的效果还不错,低电平的时间是高电平的时间的 10 倍。
现在呢,想对具体的某一个引脚而不是整个端口进行操作。换个说法就是只对寄存器的一个或者几个位进行操作,剩下的位保持不变。这个应该属于 C 语言的知识,下面以操作 PIN0 引脚为例。从仿真图中可以看出只有 PIN0 引脚的电平发生了变化,其它引脚不变。
while(1){    
        PORTC.OUT &= 0xfe;  //低电平
        _delay_ms(1);       //适当延时方便后续观察
        PORTC.OUT |= 0x01;
        _delay_us(100);     //高电平
}
GPIO 算是可以结束了,还有很多关于它的高阶知识放到后面慢慢说。
啊吖啊:与 AVR 的第一次相遇
啊吖啊:与 AVR 的第一次相遇(二)
啊吖啊:与 AVR 的第一次相遇(三)

使用特权

评论回复
18
wziyi|  楼主 | 2021-4-18 17:30 | 只看该作者
zhengshuai888 发表于 2021-4-18 15:09
楼主第一次用AVR啊。现在都很少人用这个了。

主要看它的文档配图是真心好看,

使用特权

评论回复
19
lidi911| | 2021-4-18 20:46 | 只看该作者
哈哈哈,现在AVR应该算是古董了。

使用特权

评论回复
20
嵌入小菜菜| | 2021-4-18 21:55 | 只看该作者
楼主很棒,持续关注中,很棒的资料。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

424

帖子

1

粉丝