1、2019/12/6,1,单片机片上开发方法 (ATmega16为例),王 浩 98ID: woot E-mail: ,SOC,2019/12/6,2,2019/12/6,3,你现在有这些麻烦吗?,我根本不知道怎么把单片机用在机器人上 我在自学,而且找了书在看,但越看越乱 我看了一些方案的实例,对机械部分和电路部分有感觉了,但就是不知道他们是怎样工作的 我只会用仿真器,到现在还不知道如何把写好的程序“烧”进一片真实的单片机中 只要和单片机有一点关系的电路我们就不敢设计,这让我们在写方案的过程中阻力很大。 我学过C,但是不会用它写单片机的程序 我到底是用汇编还是用C,2019/12/6,4,要解决
2、麻烦,首先假设你,会使用电脑(比如安装WindowsXP的PC) 已经学过或对C语言有一定的了解 能看得懂一些简单的电路和元器件符号 充满激情和渴望,而且有毅力和敢于动手,2019/12/6,5,我去电子市场买来一片单片机!,我能且只能这样看着它数数它的腿,瞅瞅它上面的印字!,40引脚 DIP封装,ATmega16L-8,ATmega16-16,或,2019/12/6,6,从DATASHEET中了解更多,ATMEL公司为他的所有单片机产品都提供了一份超级详细的datasheet说明书,而且对常用的系列进行了中文翻译,这将是我们接下来进行各种实验环节的第一手资料!,2019/12/6,7,从DA
3、TASHEET中了解更多,现在很多单片机内部有三种存储器: Flash EEPROM SRAM/RAM,存放程序和静态数据,单片机在工作过程中一般不能修改,一般不会使用,使用时通过特殊的命令读写,其特点是掉电不丢失,存放变量,特点是掉电丢失,2019/12/6,8,其实你还需要很多,最起码(如果想完成这里的最少一个实验的话),你还需要准备: 一支电烙铁、电烙铁架子、一小卷含铅的0.8mm焊锡和一块足够大的万用焊接电路板 一些单芯带绝缘皮的镀锡铜导线 一个40DIP插座和几根杜邦排针 8只1K的电阻和8只LED灯 一根AVR的下载线(比如USBASP线) 最好还有一个万用表,2019/12/6,
4、9,USBASP下载线,CC98上有人在做:http:/10.71.45.98/dispbbs.asp?boardID=251&ID=2351497,2019/12/6,10,下载一个开发资料包(woot整理),AVR_DEV.rar解压后,请关注论坛,即时会挂在临时ftp上并给出连接,2019/12/6,11,做好心理准备,接下来我们将为mega16单片机搭建一个最基本的电路,可以称它为一个“最小系统”,这个系统只能向单片机中下载程序并让其开始工作,然后我们会按照实验的顺序逐渐增加并完善这个系统,并让它最终成为SLOWLY机器人的一个标准系统。在这个过程中,我们会边讲、边试,不知不觉中学会使
5、用datasheet,学会在Windows上开发平台的搭建、单片机C语言编程基础、程序的下载、延时程序、LED点灯程序、I/O操作、PWM功能、定时器功能、A/D功能等片上功能的使用,2019/12/6,12,ATmega16单片机的管脚排列,PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7 RESET VCC GND XTAL2 XTAL1 PD0 PD1 PD2 PD3 PD4 PD5 PD6,PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 AREF GND AVCC PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0 PD7,2019/12/6,
6、13,从datasheet上快速知道管脚定义,AVR_DEVdatasheetcn_mega16-16L.pdf的第2页(P2),2019/12/6,14,搭建ATmega16的“最小系统”,(MOSI)PB5 (MISO)PB6 (SCK)PB7 RESET VCC GND,GND AVCC,2019/12/6,15,建议的“最小系统”,(MOSI)PB5 (MISO)PB6 (SCK)PB7 RESET VCC GND XTAL2 XTAL1,AREF GND AVCC,USBASP 下载头,插座(板子正面),VCC,GND,MOSI,MISO,SCK,RESET,+5V,+5V,104,
7、22pF,22pF,8MHz,4K7,+ 10uF,+5V,RESET,XTAL2,XTAL1,100,2019/12/6,16,增加8个LED灯用来指示,(MOSI)PB5 (MISO)PB6 (SCK)PB7 RESET VCC GND XTAL2 XTAL1,AREF GND AVCC PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0,USBASP 下载头,插座(板子正面),VCC,GND,MOSI,MISO,SCK,RESET,+5V,+5V,104,22pF,22pF,8MHz,4K7,+ 10uF,+5V,RESET,XTAL2,XTAL1,LED,1K,100,20
8、19/12/6,17,实验1:让8个LED灯闪烁,安装ICC编译器 编写让8个LED灯闪烁的程序 安装USBASP下载线驱动 使用USBASP给mega16下载写好的程序 更改mega16的熔丝位,2019/12/6,18,安装ICC编译器,双击AVR_DEVICCAVR7.13CSetup.exe,之后的图片使用ICC6.31A安装时的界面,ICC7.13的界面与其相似,2019/12/6,19,2019/12/6,20,2019/12/6,21,2019/12/6,22,C:iccv7avr,2019/12/6,23,2019/12/6,24,2019/12/6,25,2019/12/6,
9、26,2019/12/6,27,2019/12/6,28,安装ICC编译器,将AVR_DEVICCAVR7.13CICC.exe文件复制到C:iccv7avrbin目录下面。,这里是默认的目录,根据你的安装情况使用安装时设置的目录。,以后,我们可以通过双击这个文件运行ICC,可不受其30天试用期限制,但仅限于自己学习,不能用于其它用途!,2019/12/6,29,运行ICC,使用刚才的ICC.exe运行ICC7.13,2019/12/6,30,ICC的界面,2019/12/6,31,新建一个工程,Project New,2019/12/6,32,新建一个工程,建议先建立一个文件夹,如LED_t
10、est,2019/12/6,33,新建一个工程,在建立的LED_test文件夹内建立LED_project.pro文件,如图点击“保存(S)”,2019/12/6,34,2019/12/6,35,在工程中建立一个LED.c文件,File New,2019/12/6,36,2019/12/6,37,在工程中建立一个LED.c文件,File Save As,2019/12/6,38,在工程中建立一个LED.c文件,在刚建立的LED_test文件夹内保存成LED.c,2019/12/6,39,将LED.c添加到工程中,File (右击)Add File(s),2019/12/6,40,将LED.c添
11、加到工程中,选中刚才建立的LED.c文件,打开(O),2019/12/6,41,将LED.c添加到工程中,LED.c就成功添加到LED_project中了,2019/12/6,42,我们将会在这个区域里用C语言写一个LED闪烁的程序,2019/12/6,43,在开始之前,设置ICC,使其配置成为可以开发ATmega16的编译器环境,2019/12/6,44,设置你的ICC,Project Options,2019/12/6,45,设置你的ICC,如图在Target标签中的Device Configuration里选择ATmega16单片机,点击OK即可,2019/12/6,46,书写程序,程序
12、将会被写到这里,如果你是第一次使用,不妨先把下一页PPT提供的写好的程序复制到这里,熟悉一下流程先,2019/12/6,47,写好的程序,#include #include #include void InitPorts(void)DDRC = 0xFF;PORTC = 0xFF; void delay_us(unsigned int time)do time-; while (time1); void delay_ms(unsigned int time)while(time!=0) delay_us(1000); time-; void main(void)InitPorts();dela
13、y_ms(50); while(1)PORTC = 0x00;delay_ms(500);PORTC = 0xFF;delay_ms(500); ,2019/12/6,48,LED灯闪烁程序解释,#include /此头文件包含了ATmega16的口位定义等 #include /此头文件包含了AVR系列通用口位定义等 #include /*此头文件是C语言的标准头文件,在这里不写是没关系的*/,2019/12/6,49,LED灯闪烁程序解释,/端口初始化函数 void InitPorts() /*7654 3210*/DDRC = 0xFF; /PC口定义为输出PORTC = 0xFF; /P
14、C口置1(也叫“拉高”) / 1111 1111 ,2019/12/6,50,LED灯闪烁程序解释,/*8MHz晶振下*/ /微秒级延时函数 void delay_us(unsigned int time) do time-; while (time1); /毫秒级延时函数 void delay_ms(unsigned int time) while(time!=0) delay_us(1000); time-;,2019/12/6,51,LED灯闪烁程序解释,void main(void)/主程序 InitPorts();/端口初始化delay_ms(50);/延时一下,保证外部电路稳定wh
15、ile(1)/进入一个死循环PORTC = 0x00;/C口的LED灯点亮delay_ms(500);/延时500msPORTC = 0xFF;/C口的LED灯熄灭delay_ms(500);/延时100ms ,2019/12/6,52,编译,Build Project,2019/12/6,53,编译,成功,2019/12/6,54,编译后的文件,2019/12/6,55,把程序写入mega16单片机,安装USBASP下载线驱动 使用USBASP给mega16下载写好的程序,2019/12/6,56,安装USBASP下载线驱动,设置USBASP下载线的跳线 跳线说明: +5V: 连接时将通过U
16、SB接口为目标板供电。 updata: 连接时可以给USBasp进行固件升级(一般不使用)。 这里我们连接+5,断开updata,+5V,updata,2019/12/6,57,安装USBASP下载线驱动,给USBASP插上下载排线 黑色插头有突起的一侧对着板子上有白色方框的这一侧插入,2019/12/6,58,安装USBASP下载线驱动,先下载USBasp驱动: 可以在CC98代理处下载http:/10.71.45.98/uploadfile/2008/9/26/2064585665.rar 也可以在AVR_DEVprogisp167USB-Drive下找到 驱动不能直接双击安装,先把USB
17、ASP下载线插入电脑的USB口,2019/12/6,59,安装USBASP下载线驱动,电脑显示屏自动弹出下列提示框,用鼠标点击选择“是,仅这一次(Y)”,然后点击“下一步(N)”,2019/12/6,60,安装USBASP下载线驱动,当计算机屏幕显示下列提示框后,点击选择“从列表或指定位置安装(高级)(S)”,再点击“下一步(N)”,2019/12/6,61,安装USBASP下载线驱动,屏幕出现下列提示框,点击“浏览(R)”选择USBASP驱动文件所在的文件夹(USBasp-Drive),然后点击“下一步(N)”,2019/12/6,62,安装USBASP下载线驱动,2019/12/6,63,
18、安装USBASP下载线驱动,2019/12/6,64,安装USBASP下载线驱动,2019/12/6,65,使用progisp167下载软件,progisp167 是一个免费绿色软件,就在AVR_DEVprogisp167目录下,双击progisp.exe就能运行软件,2019/12/6,66,使用progisp167下载软件,(1),(2),(3),依次选择好如图设置,ATmega16,USBASP,usb,2019/12/6,67,注意下载线另一头与单片机的连接,(MOSI)PB5 (MISO)PB6 (SCK)PB7 RESET VCC GND XTAL2 XTAL1,AREF GND
19、AVCC PC7 PC6 PC5 PC4 PC3 PC2 PC1 PC0,USBASP 下载头,插座(板子正面),GND,VCC,MOSI,MISO,SCK,RESET,+5V,+5V,104,22pF,22pF,8MHz,4K7,+ 10uF,+5V,RESET,XTAL2,XTAL1,LED,1K,100,2019/12/6,68,使用progisp167下载软件,点击 “调入Flash”,(4),点击 “打开”,2019/12/6,69,使用progisp167下载软件,设置好编程方式,然后点击 “自动”,(5),2019/12/6,70,使用progisp167下载软件,说明程序已经下
20、载成功了!,2019/12/6,71,为什么会这样?,LED灯闪烁得很慢,好像根本不是1秒一次! 中间的4个LED灯根本就没有被点亮过!,2019/12/6,72,设置ATmega16的熔丝位,原因很有可能出在“熔丝位”上!,2019/12/6,73,设置ATmega16的熔丝位,新手可能根本就看不懂,下面点“向导方式”,2019/12/6,74,设置ATmega16的熔丝位,钩选,不选,不选,2019/12/6,75,设置ATmega16的熔丝位,设置好熔丝位,然后点击 “写入”,如果成功,这里会提示,2019/12/6,76,所有的LED灯都按照1s的节拍闪烁起来!,2019/12/6,7
21、7,端口初始化命令,DDRA = 0xF0; 对端口A初始化,高4位作为输出(1),低4位作为输入(0),注:金黄色字体部分表示可以根据情况更改,2019/12/6,78,写端口命令,PORTA = 0x0F; 将端口A的8个I/O口写为0000 1111,0表示I/O口拉低,1表示I/O口拉高。,注:只有在A口相应的I/O口位被定义为输出时才有实际作用,2019/12/6,79,写端口命令,P = PINA ; 读出端口A的8个I/O口上的高低电平状态,1表示高电平,0表示低电平,将其赋给P,P是无符号字节型变量(unsigned char P;),注:只有在A口相应的I/O口位被定义为输入
22、时才有实际作用,2019/12/6,80,I/O操作应用举例,LED指示灯,unsigned char P; P = PINB;/B口值给P PORTC = P; /*C口按照P的值输出。*/,DDRB = 0x00;/B口输入 DDRC = 0xFF;/C口输出,AVR ICC程序,2019/12/6,81,I/O口的一种位操作实现方法,/输出端口位操作(1为拉高,0为拉低) #define set_bit(x,y) (x|=(1y) /将x端口的第y位设置成1 /*例:*/ set_bit(PORTB,0) #define clr_bit(x,y) (x&=(1y) /将x端口的第y位设置
23、成0 /*例:*/ clr_bit(PORTB,0),2019/12/6,82,I/O口的一种位操作实现方法,/输入端口位操作(1为高电平,0为低电平) #define get_bit(x,y) (x,2019/12/6,83,实验2:使用ATmega16的ADC,将ATmega16的PA7(ADC7)口与一个光电开关连接,打开A/D转换,并用LED指示灯指示转换的高八位结果。,2019/12/6,84,实验2:使用ATmega16的ADC,电路连接(在第16张“最小系统”基础上),+5V,ADC7,100,500,56K,2019/12/6,85,与ADC相关的寄存器,Datasheet P
24、7,Datasheet P203,Datasheet P205,2019/12/6,86,与ADC相关的寄存器,Datasheet P206,2019/12/6,87,ICC程序(ADC),完整程序见备注,void ADC_init(void)/ADC初始化ADMUX|=(1ADLAR);/ADC结果左对齐ADCSRA|=(1ADPS2)|(0ADPS1)|(1ADPS0);/ADC时钟=clk/32ADCSRA|=(1ADEN);/ADC使能 void ADC_work(void) /8路共需要0.8ms左右unsigned char i=0;for(i=0;i8;i+)ADMUX/读取本路
25、转换结果,只读高8位 ,2019/12/6,88,实验3:使用ATmega16的PWM(上),使用ATmega16的PWM对电机进行调速,2019/12/6,89,L298N电机控制电路,PB4 PB5 PB6 PB7,OC0 OC2,2019/12/6,90,L298N真值表(以一个H桥为例),2019/12/6,91,ATmega16与PWM相关的寄存器,Datasheet P7,TCCR0 OCR0 TCCR2 OCR2,Datasheet P78,Datasheet P80,Datasheet P119,Datasheet P121,TCCR1A TCCR1B OCR1A OCR1B,
26、Datasheet P102,Datasheet P105,Datasheet P106,Datasheet P106,2019/12/6,92,ICC程序(PWM上),void pwm02_init(void)/PWM初始化/*OC0的PWM初始化*/TCCR0=0x00;TCCR0|=(1WGM01)|(1WGM00); /选择快速PWM方式TCCR0|=(1COM01)|(0COM00); /PWM左对齐TCCR0|=(0CS02)|(1CS01)|(1CS00); /clk/64分频OCR0=0; /OCR0的值:0255用来控制占空比,初值为0/*OC2的PWM初始化*/TCCR2=
27、0x00;TCCR2|=(1WGM21)|(1WGM20); /选择快速PWM方式TCCR2|=(1COM21)|(0COM20); /PWM左对齐TCCR2|=(0CS22)|(1CS21)|(1CS20); /clk/64分频OCR2=0; /OCR2的值:0255用来控制占空比,初值为0 ,完整程序见备注,2019/12/6,93,实验4:使用ATmega16的PWM(下),使用ATmega16的PWM控制舵机,| 黄 | 红 | 黑 | PWMVccGND,OC1A,2019/12/6,94,舵机控制原理,2019/12/6,95,ICC程序(PWM下),void pwm1_init(
28、void)/PWM初始化 /控制寄存器设置TCCR1A=0x00;TCCR1B=0x00;TCCR1B|=(0WGM13)|(1WGM12);TCCR1A|=(1WGM11)|(1WGM10);/选择成10位快速PWM模式TCCR1A|=(1COM1A1)|(0COM1A0);/PWM1A左对齐TCCR1A|=(1COM1B1)|(0COM1B0);/PWM1B左对齐TCCR1B|=(0CS12)|(1CS11)|(1CS10);/clk/64分频,Fpwm=0x7AOCR1A=197;/比较匹配1A赋初值,让右舵机回到初始状态OCR1B=175;/比较匹配1B赋初值,让左舵机回到初始状态 /0.5ms-6.1%-62 /1.5ms-18.3%-187 /2.5ms-30.5%-312 ,完整程序见备注,2019/12/6,96,Flash常量与SRAM变量,使用#pragma data:code 可以将以后的常量申请到Flash存储器中。 使用#pragma data:data 可以将以后的变量申请到SRAM存储器中。,#pragma data:code const unsigned char numC=0xF1,0xB2,0xA1,0x27; #pragma data:data unsigned char hs=0,m=0,h=0;,