因为 Balser相机要用到外部触发,故买了 Arduino单片机 提供特定PWM信号,进行外部的触发!
资料下载连接:
链接:https://pan.baidu.com/s/1k-DQLHhVLZhzKshrxOeLwA
提取码:c8oc
任务一
基本操作
第一步:安装驱动 CH340
点击,管理员运行即可
驱动安装成功后,插上单片机的USB接口i,电脑会出现相应的端口:
第二步:安装软件
点击下载的安装包,把相应的软件发送到桌面,打开即可:
第三步:相关配置
选择相应的单片机型号
选择对应的端口号
第四步:写程序并运行
闪烁一个LED灯
int ledPin = 13;
void setup() {
// put your setup code here, to run once:
pinMode(ledPin,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(ledPin,HIGH);
delay(500);
digitalWrite(ledPin,LOW);
delay(500);
}
1 是验证程序是否正确;2是下载程序到开发板里面
任务二
捕获某个端口的脉冲,并在串口中打印出来
//arduino测方波频率
int SensorINPUT = 13; //连到中断0,也就是数字引脚`
unsigned long time1,time2,time_;
float pl;
void setup()
{
Serial.begin(9600); //开启串口
pinMode(SensorINPUT, INPUT); //设置引脚输入(默认就是输入)
}
void loop()
{
int a = digitalRead(SensorINPUT); //串口打印一下看看数据正确吗
Serial.println(a);
//delay(10);
}
脉冲曲线图如下:
任务三
Arduino Uno输出自定义频率的PWM
现在需要用Arduino输出可自定义频率(20Hz)的PWM。Arduino里有简单的语句来实现PWM,但是输出信号的频率不能更改。
1、 PWM(Pulse Width Modulation)是一种方波控制信号
方波高电平的宽度在一个周期里的占比被称为占空比(Duty Cycle)。改变PWM的占空比,可以改变输出信号的平均电压,实现模拟电压的输出。
2、Arduino Uno 的 3、5、6、9、10、11 接口可以通过简单语句 analogWrite(pin, dutyCycle)
来实现一个指定占空比的PWM。其中pin的值选择(3、5,6,9,10,11),dutyCycle的值在0~255之间,0为占空比0%,255为占空比100%。但是这种方式PWM信号的频率是固定的默认值,大约1000Hz左右(16MHz/64/256)
改变频率的方式一、
手动切换高电平和低电平,再在中间加入delay函数. 我要产生 频率为20HZ, 占空比为 50%的方波,如下程序:
个人喜欢这种方式,因为我用单片机产生一个PWM波 给相机,其他的程序也没有,不占用资源!
/*
*
* 占空比为50%的方波脉冲
* 幅值4.7V,可能示波器测量有误差
* 1k Hz以内用delay,以上用delayMicroseconds
*
* 频率 f = 1/(2*delaytime)
*
* 频率 周期
* 1k Hz 0.04ms=40us
*/
const unsigned int pin = 13;
double delaytime = 25.0; //单位ms
void setup() {
pinMode(pin,OUTPUT);
digitalWrite(pin,LOW);
}
void loop() {
delay(delaytime); //单位ms
digitalWrite(pin,LOW);
delay(delaytime);
digitalWrite(pin,HIGH);
}
缺点:这种操作需要CPU全神贯注的查数,任何其他的进程的干扰会导致输出的信号频率不准
改变频率的方式二、
调节Arduino里的时钟频率
Arduino Uno里有三个Timer:Timer0,Timer1,Timer2。 三个Timer都可以自定义调整频率,但是各有特点。Timer0负责控制delay等函数,动了Timer0的频率会导致计时函数不准;Timer1的计数器是16位的,和Timer0,Timer2的8位计数器不太一样;Timer2的频率可调的档位更多,因为它有7档预除数。这里选择Timer2进行调节操作,代码如下:
void setup() {
// put your setup code here, to run once:
pinMode(3, OUTPUT);
pinMode(11, OUTPUT);
TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); //Set Timer2 to varying top limit fast PWM mode
TCCR2B = _BV(WGM22) | _BV(CS22) | _BV(CS21) | _BV(CS20);//another way to set prescaler CS2=fff
OCR2A = 155; //Top value A
OCR2B = 30; //Toggle value B, Output at pin 3
//CS2 Divisor Frequency
//001 1 31372.55
//010 8 3921.16
//011 32 980.39
//100 64 490.20 <--DEFAULT
//101 128 245.10
//110 256 122.55
//111 1024 30.64
}
void loop() {
// put your main code here, to run repeatedly:
}
由以上代码可见,需要的设置分为三个部分:pinMode,TCCR2A/B,OCR2A/B(这里的2是因为选择了Timer2)。
注释:
1、pinMode:
Timer2所控制的管脚是pin11和pin3(Timer0控制5,6;Timer1控制9,10--这是chip的datasheet上规定),所以把这两个管脚设为输出。
2、OCR2A/B:
这部分的解释需要提到Timer的结构和原理。
每个Timer里都有一个计数器和两个比较寄存器。Timer2里计数器从0数到255(8位)然后归0继续从头数;Timer2的两个比较寄存器分别为OCR2A和OCR2B。比较寄存器就是你设置一个小于255的数,比如155。当计数器数到0时输出为高电平,数到155的时候改变输出为低电平。这样就实现了占空比的调节。在普通模式下(Fast PWM),OCR2A控制pin11的占空比,OCR2B控制pin3的占空比。如下图所示:(理解)
3、TCCR2A/B:
理解了Timer的原理,下面来讨论这个PWM的频率。Arduino Uno的芯片ATmega328,晶振频率为16MHz。Timer计数器的频率会在这个基础上除以一个预除数,Timer2可选择的预除数有(1,8,32,64,128,256,1024)。也就是说,如果预除数设为64(默认),计数器计数的频率是16MHz/64 。又因为计数器要数256下才会完成一个PWM周期,所以输出PWM的频率是16MHz/64/256,约等于1000Hz。若果要获得最低的输出频率,预除数要选1024,得到的PWM是61Hz。
TCCR2A/B 就是来控制Timer2计数器的模式与预除数的大小的。先说CS2位,这个就是来控制Timer2计数器预除数的:_BV(CS22) | _BV(CS21) | _BV(CS20)
的三部分由逻辑按位或“|”链接;每个BV是按位赋注(bit value)的意思;_BV(CS22 ) = 在CS2里,1<<2(把1左移2位) = 00000100;得到三部分分别是00000100,00000010,00000001;按位或最终得到0111;查代码里的表得到对应的预除数是1024。16MHz/1024/256 = 30.5
3、模式选择:
现在的问题是,我需要的是 100Hz,不是1024预除数下的 61Hz,如何实现?这就需要控制计数器模式来 微调频率。请看下图:
这张图中的模式可以在原有的fast PWM基础上提高频率,得到图中OCnB所示的信号。这个模式叫做Varying the timer top limit: fast PWM。比较寄存器OCR2A在这里不再控制管脚11的占空比,而是设定一个计数器的上限:计数器不用数到255而是达到OCR2A就可以归零。OCR2B依然控制管脚3的占空比。
为了让pin11有活干,这里设置TCCR2A里的COM2A
位=01(表示数到极限就把pin11的电平反转,本应用不需要),COM2B
位=10(表示pin3输出非反转PWM)。
4、频率计算
到这里,所有设置已经解释完。下面来计算一下100Hz输出的PWM具体参数应该设为多少。
pin3的输出频率 = 16MHz / 1024/ (OCR2A + 1)= 100,因此100Hz对应的OCR2A=155。(+1是因为fast PWM是从0开始数到上限值)占空比 = (OCR2B+1)/ (OCR2A+1),所以: