当前位置:文档之家› 基于单片机的电机测速及显示

基于单片机的电机测速及显示

基于单片机的电机测速及显示
基于单片机的电机测速及显示

基于单片机的电机测速及显示

单片机简介 (1)

1.1单片机历史 (2)

1.2 AT89C51的主要特性 (3)

1.3管脚说明 (4)

1.4振荡器特性 (6)

1.5芯片擦除 (7)

二、硬件电路的设计 (7)

2.1 AT89C51下载器部分 (8)

2.2电机驱动部分 (11)

三、程序设计 (15)

3.1 下载器程序 (15)

3.2电机测速程序 (19)

四、总结 (26)

五、参考文献 (26)

单片机简介

单片机是一种集成在电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计时器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的计算机系统。

1.1单片机历史

单片机诞生于20世纪70年代末,经历了SCM、MCU、SoC三大阶段。

(1)SCM即单片微型计算机(Single Chip Microcomputer)阶段,主要是寻求最佳的单片形态嵌入式系统的最佳体系结构。“创新模式”获得成功,奠定了SCM与通用计算机完全不同的发展道路。在开创嵌入式系统独立发展道路上,Intel公司功不可没。(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)

Micro Controller Unit

(2)MCU即微控制器(Micro Controller Unit)阶段,主要的技术发展方向是:不断扩展满足嵌入式应用时,对象系统要求的各种外围电路与接口电路,突显其对象的智能化控制能力。它所涉及的领域都与对象系统相关,因此,发展MCU的重任不可避免地落在电气、电子技术厂家。从这一角度来看,Intel逐渐

淡出MCU的发展也有其客观因素。在发展MCU方面,最著名的厂家当数Philips公司。

Philips公司以其在嵌入式应用方面的巨大优势,将MCS-51从单片微型计算机迅速发展到微控制器。因此,当我们回顾嵌入式系统发展道路时,不要忘记Intel和Philips的历史功绩。1.2 AT89C51的主要特性

·与MCS-51 兼容

·4K字节可编程闪烁存储器

·寿命:1000写/擦循环

·数据保留时间:10年

·全静态工作:0Hz-24Hz

·三级程序存储器锁定

·128*8位内部RAM

·32可编程I/O线

·两个16位定时器/计数器

·5个中断源

·可编程串行通道

·低功耗的闲置和掉电模式

·片内振荡器和时钟电路

1.3管脚说明

VCC:供电电压。

GND:接地。

P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。

P1口:P1口是一个内部提供上拉电阻的8位双向I/O 口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)

P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控

制信号。

P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。

P3口也可作为AT89C51的一些特殊功能口,如下表所示:

P3.0 RXD(串行输入口)

P3.1 TXD(串行输出口)

P3.2 /INT0(外部中断0)

P3.3 /INT1(外部中断1)

P3.4 T0(记时器0外部输入)

P3.5 T1(记时器1外部输入)

P3.6 /WR(外部数据存储器写选通)

P3.7 /RD(外部数据存储器读选通)

P3口同时为闪烁编程和编程校验接收一些控制信号。

RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而

要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。

(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)

/PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

/EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。

XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。

XTAL2:来自反向振荡器的输出。

1.4振荡器特性

XTAL1和XTAL2分别为反向放大器的输入和输出。该反向放大器可以配置为片内振荡器。石晶振荡和陶瓷振荡均可采用。如采用外部时钟源驱动器件,XTAL2应不接。有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度。

1.5芯片擦除

整个PEROM阵列和三个锁定位的电擦除可通过正确的控制信号组合,并保持ALE管脚处于低电平10ms 来完成。在芯片擦操作中,代码阵列全被写“1”且在任何非空存储字节被重复编程以前,该操作必须被执行。(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)此外,AT89C51设有稳态逻辑,可以在低到零频率的条件下静态逻辑,支持两种软件可选的掉电模式。在闲置模式下,CPU停止工作。但RAM,定时器,计数器,串口和中断系统仍在工作。在掉电模式下,保存RAM的内容并且冻结振荡器,禁止所用其他芯片功能,直到下一个硬件复位为止。

二、硬件电路的设计

2.1 AT89C51下载器部分

SP-51Pro(即Easy51pro)编程器可以烧录Atmel公司系列单片机芯片,具有性能稳定,烧录速度快,性价比高等优点。产品性能介绍如下:

⑴支持的芯片

支持目前最为经典和市场占有量最大的ATMEL公司生产的AT89C51、C52、C55和最新的S51、S52;AT89C1051、2051、4051等芯片。

⑵产品特点

1.使用串口通讯,芯片自动判别,编程过程中的擦除、烧写、校验各种操作完全由编程器上的监控芯片89C51控制,不受PC配置及其主频的影响,因此烧写成功率高可以达到100%,烧写速度很快并且烧写速度和微机的档次无关。(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)

2.采用57600高速波特率进行数据传送,编程速度可以和一般并行编程器相媲美,经测试,烧写一片4K ROM的AT89C51仅需要9.5S,而读取和校验仅需要

3.5S。

3.体积小巧,省去笨重的外接电源适配器,直接使用USB端口5V电源, 携带方便,非常初学者学习51单片机的要求。

4.软件界面友好,菜单、工具栏、快捷键齐全,全中文操作,提供加密功能,可以保护您的创作产权。可以说是麻雀虽小,五脏俱全!

5.功能完善,具有编程、读取、校验、空检查、擦除、加密等系列功能;

6.40pin和20pin锁紧插座,所有器件全部以第一脚对齐,无附加跳线,对于DIP封装芯片无需任何适配器;

7.采用优质万用锁紧插座,和接触不良等问题彻底说再见,可烧写40脚单片机芯片和20脚单片机芯片

8.改进的烧写深度确保每一片C51系列芯片的反复烧写次数都能达

到1000以上!内部数据至少保存10年。

9.因为采用了9针传口通讯,这样一来就不会再和打印机抢一个打印口,随时随地想烧就烧,让芯片编程成为一种快乐!

(3)硬件连接

1.通讯电缆与编程器连接好,

2.将串口插头插入电脑串口,

https://www.doczj.com/doc/9916888953.html,B插头插入电脑任一个USB口,此时编程器上LED点亮,表明电源接通。(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)

4.接着安装软件,本软件支持Win9x/me/2000/NT,标准Window操作界面。本软件属于绿色软件,不需要安装,直接把相关的软件拷贝到硬盘中,运行其中的Easy 51Pro 2_0程序即可。

⑷软件使用

程序启动后,会自动检测硬件及连接,状态框中显示“就绪”字样,表示编程器连接和设置均正常。否则请检查硬件连接和端口设置。(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)

把单片机芯片正确地放到编程器的相应插座上,注意,芯片的缺口要朝向插座的把手方向。

芯片放好后,就可以对芯片进行读写操作了,读写操作按下面的步骤进行:

1、程序运行,请先选择器件(点下选框)

2、用“打开文件”选择打开要编写的.HEX 和 .BIN 文件

3、用“保存文件”可以保存读出来的文件

4、用“擦除器件”擦除芯片

5、用“写器件”编程

6、用“读器件”读取芯片中的程序,加密的读不出来

7、用“校验数据”检查编程的正确与否

8、用“自动完成”自动执行以上各步骤

9、用“加密”选择加密的级数2.12电机驱动部分

2.2电机驱动部分

图4-3中所示为一个典型的直流电机控制电路。电路得名于“H 桥驱动电路”是因为它的形状酷似字母H。4个三极管组成H的4条垂直腿,而电机就是H中的横杠(注意:图4.12及随后的两个图都只是示意图,而不是完整的电路图,其中三极管的驱动电路没有画出来)。(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)

如图所示,H桥式电机驱动电路包括4个三极管和一个电机。要使电

机运转,必须导通对角线上的一对三极管。根据不同三极管对的导通情况,电流可能会从左至右或从右至左流过电机,从而控制电机的转向。

图4-3 H桥简易驱动电路要使电机运转,必须使对角线上的一对三极管导通。例如,如图4-4所示,当Q1管和Q4管导通时,电流就从电源正极经Q1从左至右穿过电机,然后再经Q4回到电源负极。按图中电流箭头所示,该流向的电流将驱动电机顺时针转动。当三极管Q1和Q4导通时,电流将从左至右流过电机,从而驱动电机按特定方向转动(电机周围的箭头指示为顺时针方向)。

图4-4 H桥电路驱动电机顺时针转动

图4-5所示为另一对三极管Q2和Q3导通的情况,电流将从右至左流过电机。当三极管Q2和Q3导通时,电流将从右至左流过电机,从而驱动电机沿另一方向转动(电机周围的箭头表示为逆时针方向)。

图4-5 H桥驱动电机逆时针转动

驱动电机时,保证H桥上两个同侧的三极管不会同时导通非常重要。如果三极管Q1和Q2同时导通,那么电流就会从正极穿过两个三极管直接回到负极。此时,电路中除了三极管外没有其他任何负载,因此电路上的电流就可能达到最大值(该电流仅受电源性能限制),甚至烧坏三极管。基于上述原因,在实际驱动电路中通常要用硬件电路方便地控制三极管的开关。

图4-6 所示就是基于这种考虑的改进电路,它在基本H桥电路的基础上增加了4个与门和2个非门。4个与门同一个“使能”导通信号相接,这样,用这一个信号就能控制整个电路的开关。而2个非门通过提供一种方向输人,可以保证任何时候在H桥的同侧腿上都只有一个三极管能导通。(与本节前面的示意图一样,图4.15所示也不

是一个完整的电路图,特别是图中与门和三极管直接连接是不能正常工作的。)(本文由点梦时刻 https://www.doczj.com/doc/9916888953.html, 倾情奉献)

图4-6 具有使能控制和方向逻辑的H桥电路采用以上方法,电机的运转就只需要用三个信号控制:两个方向信号和一个使能信号。如果DIR-L信号为0,DIR-R信号为1,并且使能信号是1,那么三极管Q1和Q4导通,电流从左至右流经电机(如图4.-7所示);如果DIR-L信号变为1,而DIR-R信号变为0,那么Q2和Q3将导通,电流则反向流过电机。

图4-7 使能信号与方向信号的使用

实际使用的时候,用分立元件制作H桥是很麻烦的,好在现在市面上有很多封装好的H桥集成电路,接上电源、电机和控制信号就可以使用了,在额定的电压和电流内使用非常方便可靠。比如常用的L293D、L298N、TA7257P、SN754410等。

三、程序设计

3.1 下载器程序

#include

BYTE ComBuf[18];

UINT nAddress;

UINT nTimeOut;

ProWork pw;

void Delay_us(BYTE nUs)

{

TH0=0;

TL0=0;

TR0=1;

while(TL0

{

}

TR0=0;

}void Delay_ms(UINT nMs)

{

UINT n=0;

TR0=1;

while(n

{

TH0=0;

TL0=20;

while(TH0<4)

{

}

n++;

}

TR0=0;

}

BOOL WaitComm()//等待上位机的命令,18字节

{

BYTE n=0;

RI=0;

while(!RI){}/

ComBuf[n]=SBUF;

RI=0;

n++;

for(n;n<=17;n++)

{

nTimeOut=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>10000)

return 0;

}

ComBuf[n]=SBUF;

RI=0;

}

return 1;

}

BOOL WaitResp(){

nTimeOut=0;

RI=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>50000)

{

return 0;

}

}

RI=0;

ComBuf[0]=SBUF;

return 1;

}

BOOL WaitData()

{

BYTE n;

RI=0;

for(n=0;n<=17;n++)

{

nTimeOut=0;

while(!RI)

{

nTimeOut++;

if(nTimeOut>10000)

{

return 0;

}

}

RI=0;

ComBuf[n]=SBUF;

}

return 1;

}

void SendData()//发送数据或回应操作完成,18字节

{

BYTE n=0;

for(n;n<=17;n++)

{

TI=0;

SBUF=ComBuf[n];

while(!TI){}

TI=0;

}

}

void SendResp()

{

TI=0;

SBUF=ComBuf[0];

while(!TI){}

TI=0;

}

void SetVpp5V()//设置Vpp为5v

{

P3_4=0;

P3_3=0;

}

void SetVpp0V()//设置Vpp为0v

{

P3_3=0;

P3_4=1;

}

void SetVpp12V()//设置Vpp为12v

{

P3_4=0;

P3_3=1;

}

void RstPro()

{

pw.fpProOver();

SendData();

}

void ReadSign()//读特征字{

pw.fpReadSign();

SendData();

}

void Erase()

{

pw.fpErase();

SendData();

}

void Write(

{

BYTE n;

pw.fpInitPro();

SendData();

while(1)

{

if(WaitData())

{

if(ComBuf[0]==0x07)

{

for(n=2;n<=17;n++)

{

if(!pw.fpWrite(ComBuf[n]) )

{

pw.fpProOver();

ComBuf[0]=0xff;

SendResp();

WaitData();

return;

}

nAddress++;//下一个单元

}

ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续

SendResp();

}

else

if(ComBuf[0]==0x00)//写器件结束

break;

else//可能是通讯出错了

{

pw.fpProOver();

return;

}

}

else//等待数据失败

{

pw.fpProOver();

return;

}

}

pw.fpProOver();

Delay_ms(50);

ComBuf[0]=0;

SendData();

}

void Read()//

{

BYTE n;

pw.fpInitPro();

SendData();

while(1)

{

if(WaitResp())/

{

if(ComBuf[0]==0)

{

break;

}

else

if(ComBuf[0]==0xff)//0xff表示重发

{

nAddress=nAddress-0x0010;

}

for(n=2;n<=17;n++)

{

ComBuf[n]=pw.fpRead();

nAddress++;//下一个单元

}

ComBuf[0]=6;//向上位机发送读出的数据块

SendData();

}

else

break;//等待回应失败

}

pw.fpProOver();//操作结束设置为运行状态

ComBuf[0]=0;//通知上位机编程器进入就绪状态

SendData();

}

void Lock()//写锁定位

{

pw.fpLock();

SendData();

}

extern void PreparePro00(); extern void preparePro01();

extern void PreparePro02();//FID=02:AT89

S51编程器

void main()

{

SP=0x60;

SetVpp5V();//先初始化Vpp

为5v

SCON=0x00;

TCON=0x00;

//PCON=0x00;//波特率*2

IE=0x00;

//TMOD:

GATE|C/!T|M1|M0|GATE|C/!T|M1

|M0

// 0 0 1 0 0 0 0 1

TMOD=0x21;//T0用于延时程

TH1=0xff;

TL1=0xff;//波特率28800*2,

注意PCON

//SCON:

SM0|SM1|SM2|REN|TB8|RB8|TI|R

I

// 0 1 0 1 0 0 0 0

SCON=0x50;

TR1=1;

Delay_ms(1000);//延时1秒

后编程器自举

ComBuf[0]=0;

SendData();

while(1)//串口通讯采用查

询方式

{

if(!WaitComm())//如果超时,通讯出错

{

Delay_ms(500);

ComBuf[0]=0;//让编程器复位,使编程器就绪

}

switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针

{

case 0://at89c51编程器

PreparePro00();

break;

case 1://at89c2051编程器

PreparePro01();

break;

case 2://at89s51编程器

PreparePro02();

break;

//case 3:支持新器件时,请继续向下添加

// break;

//case 4:

// break;

default:

ComBuf[0]=0xff;

ComBuf[1]=0xff;//表示无效的操作

break;

}

switch(ComBuf[0])//根据操作ID跳到不同的操作函数

{

case 0x00:

RstPro();//编程器复位

break;

case 0x01:

ReadSign();//读特征字

break;

case 0x02:

Erase();//擦除器件

break;

case 0x03:

Write();//写器件

break;

case 0x04:

Read();//读器件

break;

case 0x05:

Lock();//写锁定位

break;

default:

SendData();

break;

}

}

}

3.2电机测速程序

/*

LED.C

128×64 LED驱动程序头文件*/

#ifndef LED_H_ #define LED_H_

#include

//定义背光控制信号

sbit LED_BL=P1^4;

//点亮背光灯

void LEDLightOn();

//熄灭背光灯

void LEDLightOff();

//清屏

void LEDClear();

//初始化

void LEDInit();

//显示ASCⅡ码

void LEDPutChar(unsigned char c);

//显示字符串

void LEDPuts(unsigned char*s);

#endif //LED_H_

/*

LED.C

128×64 LED驱动程序

*/

#include

#include

//#include "LED.H"

//定义屏幕光标(取值0~63,光标本身不可见)

unsigned char LEDCursor;

int i,j;

/*

函数:LEDLightOn()

功能:点亮背光灯

*/

void LEDLightOn()

{

LED_BL = 1;

}

/*

函数:LEDLightOff()

功能:熄灭背光灯

*/

void LEDLightOff()

{

LED_BL = 0;

}

/*

函数:LEDGetBF()

功能:读出状态位BF

返回:

BF=1,表示忙,不可进行任何操作

BF=0,表示不忙,可以进行正常操作

*/

bit LEDGetBF()

{

unsigned char dat;

dat = XBYTE[0xD002];

//XBYTE的定义见

return (bit)(dat & 0x80);

相关主题
文本预览
相关文档 最新文档