这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » Arduino在嵌入式开发中应用案例之arduino点亮LED

共2条 1/1 1 跳转至

Arduino在嵌入式开发中应用案例之arduino点亮LED

工程师
2020-12-06 23:00:23     打赏

你了解什么是Arduino吗?你知道Arduino能做些什么吗?今天就让我们来认识一下Arduino!

Arduino是一款便捷灵活、方便上手的开源电子原型平台。

包含硬件(各种型号的Arduino板)和软件(ArduinoIDE)。由一个欧洲开发团队于2005年冬季开发。其成员包括MassimoBanzi、DavidCuarTIelles、TomIgoe、GianlucaMarTIno、DavidMellis和NicholasZambetTI等。

本分享一个通过arduino点亮LED的案例。

硬件设备
  • ArduinoUno开发板

  • 台式机

  • Arduino到台式机连接线

软件
  • AtmelStudio

    • 安装AtmelStudio,里面会有atmel的编译器,还会安装PC端的virtualcommportdriver用来打印信息到TeraTerm

    • 当然也可以下载一个ArduinoIDE,ArduinoIDE可以快速地对Arduino进行编程,但我比较习惯用AtmelStudio。

  • AvrDude

    • 这个软件可以通过串口下载代码到Arduino

  • 串口通信软件,putty或者TeraTerm

  • 代码编辑软件,Atom或者其他任何可以编辑文本的软件

文档
  • Arduino的CPUAtmel328P的芯片手册,下载链接。

开启Arduino之旅项目介绍

这个小项目主要是带大家入门嵌入式开发领域。

  • 点亮自己的LED小灯

  • 通过串口进行debug

  • 写一个简单的commandlineinterface用来和板子通信

初识Arduino硬件

我们的核心是ArduinoUno开发板,下面这张图是Arduino的电路图。我把它的几个大块标记出来,下面我一一来说明下。

  • VoltageRegulator:它的任务是为系统提供稳定的3.3V和5V的电压。在蓝色区域有两个voltageregulator,一个是LP2985,输入5V,输出3.3V;一个是NCP1117,输入最高20V,输出5V。Arduino的供电有两种,一种是USB供电,这时候只从蓝色区域左下角的USBVCC为板子提供5V电压,然后通过一个regulator为板子提供3.3V电压。另一种供电是通过供电插口(在板子上USB插口的下方有个圆形的黑色电源插口),这个供电插口是蓝色区域中靠中间的长方形区域,它的电压可以最高到20V,然后通过NCP1117变成5V电压,然后再通过LP2985变成3.3V电压。这里面有个值得注意的地方是蓝色区域的USBVCC出来后连接了一个三极管,三极管上面有个比较器,比较器的正向输入端连接了一个分压电路,反向输入端连接着3.3V。它的目的是如果从供电插口输入的电压不足5V,那就用USB的5V电压,否则就用供电插口的5V电压。

  • USBControlchip:USB的控制芯片,买回来的Arduino中这个芯片的固件都是已经在里面的,它的作用是把USB接口的东西转成串行通信数据(在电路图红色的SerialComm部分)发送给CPU,还用把CPU从串行通信发出来的东西,传换成USB信号发送给PC机。

  • MainCPU:主CPU是Atmel328P。8-bitCPU,因为Arduino没有外接的serialflash或者外接的SDRAM,所以根据芯片手册,一共有32KB芯片上的programmingflash,编译的代码可以放在这个flash里面。有2KB的SRAM,一些寄存器的信息,stack和heap,全局变量等都放在RAM里。

  • Crystal:16MHz的晶振

  • LED:LED的输入标记是SCK,对应连接的是atmel328P上的B5管脚。LED连接了一个放大器,目的是电流不通过放大器,只是通过电压来控制LED,这样的话B5管脚可以做其他用途。

  • SerialComm:串口通信端口,在CPU上通过usart给PC端发送数据。

点亮ArduinoLED小灯创建项目
  • 选择File->Project->GCCexecutableproject

    • 输入项目名称,之后的芯片请选择atmel328p

  • 然后需要配置avrdude,选择tool->externaltool开始配置avrdude

    • TItle:avrdudeprogrammer

    • Command:C:avrdudeavrdude.exe请填写到avrdude的路径。

    • Arguments:-F-V-carduino-pATMEGA328P-PCOM6-b115200-Uflash:w:"$(ProjectDir)Debug$(ItemFileName).hex":i里面的COM6请从devicemanager中找出当前的commport.

点亮LED灯
  • 点亮LED灯,需要配置PB5GPIO寄存器。通过Atmel328p的datasheet和Arduino的电路图,输出高电平使LED亮,输出低电平使LED灭。

DDRB|=(1<< PB5);//配置PB5的datadirecTIonregisterPORTB|=(1<< PB5);//使PB5输出高电平PORTB&=~(1<< PB5);//使PB5输出低电平
串口通信
  • 当能够控制LED的开关,这时候可以说明编译器和Avrdude的代码下载也没问题。这时候为了我们更好地debug程序,我们需要让串口通信正常工作,这样可以把信息打印到PC端。

  • 根据Arduino电路图,我们需要让红色区域的serialcomm正常工作。USBcontrollerchip可以把数据从USB端口输出到PC端。

  • 在atmel328P的datasheet,section24。有详细的USART的描述,对于USART来说,首先肯定是要配置波特率了,然后需要配置USART的一些传输模式,比如一次发8bit或者一次发7bit,有没有stopbit等等。

    • 要注意的是datasheet里面给出了如何把波特率计算成寄存器需要的值,计算公式和板子的晶振频率有关。具体在数据手册第227页。

  • 在传输过程,就是不断的把想要发送的数据写到寄存器里,然后Atmel328P会通过两个pin发送到USBcontrollerchip,然后USBcontrollerchip再发送给PC端。

//配置USARTUBRR0H=(uint8_t)(BAUDRATE_9600_UBRR>>8);//配置波特率UBRR0L=(uint8_t)BAUDRATE_9600_UBRR;UCSR0B=(1<<rxen0) |="" (1<<txen0) |="" (1<< RXCIE0);   //enable接收和发送数据UCSR0C=(3<<ucsz00); //配置发送模式,8bit数据1bitstopbit
//发送数据voidUSART_Transmit(uint8_t*Data,uint16_tLength){uint16_ti;for(i=0;i< Length; i++)
 {    /*Waitforemptytransmitbuffer*/while(!(UCSR0A&(1<<udre0))); /*Putdataintobuffer,sendsthedata*/UDR0=Data[i];}}
//接收数据,使用中断接收数据ISR(USART_RX_vect){uint8_tReceivedData;ReceivedData=UDR0;}
CommandLineInterface
  • 当确定Arduino和PC端可以正常通信,我们就可以开始写commandlineinterface。顾名思义,是通过PC端输入指令,Arduino做相应的动作。一般大部分的电子产品都有自己的cli用来和产品通信,很多情况如果要开发新的功能,就增加一条新的command,然后PC端的driver可以发送这个新的command给嵌入式设备,这样它就可以执行新的功能了。

  • commandlineinterface源码,里面可以输入指令使Arduino的LED开启或者关闭。

  • 在commandlineinterface的实现过程中,有些蛮有趣的地方。

    • 我用了一个circularbuffer来实现数据的接收和处理,有一个readindex和一个writeindex,使用buffer的目的就在于用户输入命令的速度要和计算机处理的速度不同,所以我们需要一个buffer来平衡它们。比如计算机要处理某个命令需要很久,而用户在这个命令后又连续输入了好几个其他的命令,所有其他的命令都会放到这个circularbuffer然后依次处理。

    • 这个小project使用了这个volatile来定义一个变量,USART_StartCmdProcess,用来记录当前在receivebuffer中有多少个命令。原因是我们是在中断中把这个变量自加1,当编译器编译这段代码的时候,如果没有volatile的话,编译器并不知道什么时候这个变量什么时候会加1,因为中断在任何时候都可能发生。因此在主函数里面有if(变量>0),这个判断会被编译器认为永远不会发生(编译器将这个判断为永远false)。所以加了volatile就强制编译器在编译去真正判断地判断变量的值,简单地说是不会优化主函数里面地if(变量>0)。

  • 输入GetLedStatus,Arduino返回LEDOFF

  • 输入SetLedON,Arduino点亮LED

  • 输入GetLedStatus,Arduino返回LEDON

  • 输入SetLedOFF,Arduino关闭LED




工程师
2020-12-09 22:48:22     打赏
2楼

案列还是非常不错的


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]