时间:2020-11-26 17:39
人气:
作者:admin
你了解什么是Arduino吗?你知道Arduino能做些什么吗?今天就让我们来认识一下Arduino!
Arduino是一款便捷灵活、方便上手的开源电子原型平台。
包含硬件(各种型号的Arduino板)和软件(Arduino IDE)。由一个欧洲开发团队于2005年冬季开发。其成员包括Massimo Banzi、David CuarTIelles、Tom Igoe、Gianluca MarTIno、David Mellis和Nicholas ZambetTI等。
本分享一个通过arduino点亮LED的案例。
需要的工具
Arduino Uno开发板
台式机
Arduino到台式机连接线
Atmel Studio
安装Atmel Studio,里面会有atmel的编译器,还会安装PC端的virtual comm port driver用来打印信息到TeraTerm
当然也可以下载一个Arduino IDE,Arduino IDE可以快速地对Arduino进行编程,但我比较习惯用Atmel Studio。
AvrDude
这个软件可以通过串口下载代码到Arduino
串口通信软件,putty 或者 TeraTerm
代码编辑软件,Atom 或者其他任何可以编辑文本的软件
Arduino的CPU Atmel328P的芯片手册,下载链接。
这个小项目主要是带大家入门嵌入式开发领域。
点亮自己的LED小灯
通过串口进行debug
写一个简单的command line interface用来和板子通信
我们的核心是Arduino Uno开发板,下面这张图是Arduino的电路图。我把它的几个大块标记出来,下面我一一来说明下。
Voltage Regulator: 它的任务是为系统提供稳定的3.3V和5V的电压。在蓝色区域有两个voltage regulator,一个是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电压。
USB Control chip: USB的控制芯片,买回来的Arduino中这个芯片的固件都是已经在里面的,它的作用是把USB接口的东西转成串行通信数据(在电路图红色的Serial Comm部分)发送给CPU,还用把CPU从串行通信发出来的东西,传换成USB信号发送给PC机。
Main CPU: 主CPU是Atmel328P。8-bit CPU, 因为Arduino没有外接的serial flash 或者外接的SDRAM,所以根据芯片手册,一共有32KB 芯片上的programming flash,编译的代码可以放在这个flash里面。有2KB的SRAM,一些寄存器的信息,stack和heap,全局变量等都放在RAM里。
Crystal: 16MHz的晶振
LED: LED的输入标记是SCK,对应连接的是atmel328P上的B5管脚。LED连接了一个放大器,目的是电流不通过放大器,只是通过电压来控制LED,这样的话B5管脚可以做其他用途。
Serial Comm: 串口通信端口,在CPU上通过usart给PC端发送数据。

选择File -> Project -> GCC executable project
输入项目名称,之后的芯片请选择atmel328p
然后需要配置avrdude, 选择tool -> external tool开始配置avrdude
Title:avrdude programmer
Command: C:avrdudeavrdude.exe 请填写到avrdude的路径。
Arguments: -F -V -c arduino -p ATMEGA328P -P COM6 -b 115200 -U flash:w:"$(ProjectDir)Debug$(ItemFileName).hex":i 里面的COM6请从device manager中找出当前的comm port.
点亮LED灯,需要配置PB5 GPIO寄存器。通过Atmel328p的data sheet和Arduino的电路图,输出高电平使LED亮,输出低电平使LED灭。
DDRB |= (1 << PB5); //配置PB5的data direction register
PORTB |= (1 << PB5); //使PB5输出高电平
PORTB &= ~(1 << PB5); //使PB5输出低电平
当能够控制LED的开关,这时候可以说明编译器和Avrdude的代码下载也没问题。这时候为了我们更好地debug程序,我们需要让串口通信正常工作,这样可以把信息打印到PC端。
根据Arduino电路图,我们需要让红色区域的serial comm正常工作。USB controller chip可以把数据从USB端口输出到PC端。
在atmel328P的data sheet, section 24。有详细的USART的描述,对于USART来说,首先肯定是要配置波特率了,然后需要配置USART的一些传输模式,比如一次发8 bit 或者一次发7 bit,有没有stop bit等等。
要注意的是data sheet里面给出了如何把波特率计算成寄存器需要的值,计算公式和板子的晶振频率有关。具体在数据手册第227页。
在传输过程,就是不断的把想要发送的数据写到寄存器里,然后Atmel328P会通过两个pin发送到USB controller chip,然后USB controller chip再发送给PC端。
//配置USART
UBRR0H = (uint8_t)(BAUDRATE_9600_UBRR >> 8); // 配置波特率
UBRR0L = (uint8_t)BAUDRATE_9600_UBRR;
UCSR0B = (1<1<1 << RXCIE0); //enable接收和发送数据
UCSR0C = (3<//配置发送模式,8 bit 数据 1 bit stop bit
//发送数据
void USART_Transmit(uint8_t * Data, uint16_t Length)
{
uint16_t i;
for (i = 0; i < Length; i++)
{
/* Wait for empty transmit buffer */
while (!( UCSR0A & (1</* Put data into buffer, sends the data */
UDR0 = Data[i];
}
}
//接收数据, 使用中断接收数据
ISR(USART_RX_vect)
{
uint8_t ReceivedData;
ReceivedData = UDR0;
}
当确定Arduino和PC端可以正常通信,我们就可以开始写command line interface。顾名思义,是通过PC端输入指令,Arduino做相应的动作。一般大部分的电子产品都有自己的cli用来和产品通信,很多情况如果要开发新的功能,就增加一条新的command,然后PC端的driver可以发送这个新的command给嵌入式设备,这样它就可以执行新的功能了。
command line interface源码, 里面可以输入指令使Arduino的LED开启或者关闭。
在command line interface的实现过程中,有些蛮有趣的地方。
我用了一个circular buffer来实现数据的接收和处理,有一个read index和一个write index,使用buffer的目的就在于用户输入命令的速度要和计算机处理的速度不同,所以我们需要一个buffer来平衡它们。比如计算机要处理某个命令需要很久,而用户在这个命令后又连续输入了好几个其他的命令,所有其他的命令都会放到这个circular buffer然后依次处理。
这个小project使用了这个volatile来定义一个变量, USART_StartCmdProcess,用来记录当前在receive buffer中有多少个命令。原因是我们是在中断中把这个变量自加1,当编译器编译这段代码的时候,如果没有volatile的话,编译器并不知道什么时候这个变量什么时候会加1,因为中断在任何时候都可能发生。因此在主函数里面有if (变量 > 0),这个判断会被编译器认为永远不会发生(编译器将这个判断为永远false)。所以加了volatile就强制编译器在编译去真正判断地判断变量的值,简单地说是不会优化主函数里面地if (变量 > 0)。
输入GetLedStatus, Arduino返回LED OFF
输入SetLed ON,Arduino点亮LED
输入GetLedStatus, Arduino返回LED ON
输入SetLed OFF, Arduino关闭LED
原文标题:Arduino在嵌入式开发中的应用举例
文章出处:【微信公众号:STM32嵌入式开发】欢迎添加关注!文章转载请注明出处。