历史上的今天
返回首页

历史上的今天

今天是:2024年10月20日(星期日)

正在发生

2021年10月20日 | 【自学51单片机】9 -- 步进电机原理、蜂鸣器原理,单片机IO

2021-10-20 来源:eefocus

【自学51单片机】9 -- 步进电机原理、蜂鸣器原理,单片机IO口的结构,上下拉电阻


1、单片机IO口的结构

单片机IO口有四种结构:准双向IO,开漏输出、强推挽输出和高阻态输出。内部结构如下图。

T1和T2为MOS管,靠电压导通的原件。(1)准双向IO口特点:内部输出为1,才能正常读取外部信号。(2)开漏输出特点:必须外加上拉电阻,不然单片机IO电平是个不确定的态。(3)强推挽输出特点:可输出或输入高电流,驱动能力强。(4)强阻态特点:状态取决与外部输入。 标准51单片机P0默认开漏输出。


2、上下拉电阻

上下拉电阻:上拉电阻就是将不确定的信号通过一个电阻拉到高电平,同时此电阻也起限流作用,下拉电阻同理。


上拉电阻的应用:(1)OC门(开漏输出中,三极管的集电极)要输出高电平,外部必须加上拉电阻(2)加大普通IO口的驱动能力(3)起到限流的作用(4)抵抗电磁干扰

电路设计中如何选择上下拉电阻阻值:(1)从降低功耗方面考虑应该足够大,因为电阻越大,电流越小。(2)从确保足够的引脚驱动能力考虑应该足够小,电阻越小,电流才能越大。(3)开漏输出时,过大的上拉电阻会导致信号上升沿变缓,解释:电平变化需要时间,开漏输出时,上拉电阻的大小直接影响电平上升的时间,如下图所示。

3、电机

3.1 电机分类

从用途角度分为: 驱动类电机和控制类电机。直流电机属于驱动类电机,这种电机是将电能转换成机械能,应用在电风扇、洗衣机等。步进电机属于控制类电机,它是将脉冲信号转换成一个转动角度的电机,应用在机器人,空调扇叶转动等。



步进电机分为:反应式、永磁式和混合式三种。(1)反应式:结构简单,成本低,性能差(2)永磁式:动态性能好,力矩较大,转动误差相对大一些。(3)混合式:动态性能好,力矩大,转动精度高。


3.2 28BYJ-48型步进电机

28BYJ-48实物如下图9-3

1、28 — 步进电机的有效最大外经28mm。

2、B — 表示是步进电机。

3、Y — 表示为永磁式。

4、J — 表示是减速型。

5、48 — 表示四相八拍


步进电机结构原理如下图9-4

标注为0~5的齿叫转子,转子是一块永磁体,上带有永久磁性。外圈的齿为定子,图片上有8个,它是固定的。每个定子都绕了线圈绕组,正对的两个定子绕组是串联在一起的,这两定子组成一相。图中一共有A-B-C-D四相。


28BYJ-48电机结构原理如下图

定子上拥有 4 相×8 组=32 个齿。


3.2 28BYJ-48电机转动原理

在这里插入图片描述
在这里插入图片描述

**原理:**由实物图和原理图可知,红线为公共端,橙,黄,粉,蓝对应A-B-C-D相,P1.0~~P1.3分别控制进步电机的A-B-C-D相,导通D相只需让P1.3输出高电平,使Q5

三极管导通,三极管基极b接地,即能导通A相。导通其他相同理,导通后对应相的定子产生磁性,就会对靠近的转子产生吸引力,使转子转动。


3.3 28BYJ-48电机工作模式

步进电机单四拍模式:单相绕组通电四节拍 。假如一开始电机为28BYJ-48电机结构原理里的状态,完成D-C-B-A依次导通后,即完成4个节拍后,转子会因为吸引力转动转过一组绕组。而每经过 1 个单拍,转子都将转过一个定子齿的角度,转一整圈就需要 4×8=32节拍。一个节拍转子转过11.25度(360/32 ),这个值叫步进角度。


步进电机八拍模式:在单四拍模式的每两个节拍之间再插入一个双绕组导通的中间节拍,比如在单独A导通和单独B导通中间加一个同时A和B导通的节拍。这样转子转一圈就需要8 x 8 = 64节拍。一个节拍转子转过5.625度,相比单四拍模式,该模式转动精度更加精准,输出力矩更大。下面看八拍模式绕组控制顺序表。

从上面表中,可以得到把八节拍下P1的低四位IO控制代码


unsigned char code BeatCode[8] = {

0xE, 0xC, 0xD, 0x9, 0xB, 0x3, 0x7, 0x6

};


3.4 步进电机启动频率

控制电机切换一次节拍需要多长时间?

这个时间由步进电机的启动频率决定,在步进电机空载下不高于启动频率就可以正常启动电机。下面见28BYJ-48电机参数表。

表中28BYJ-48电机启动频率为550.单位P.P.S,即每秒脉冲数,通过计算可以知道单个节拍持续时间应该大于1 / 500 =1.8ms即可让电机正常工作。


3.5 实际28BYJ-48电机外部转轮转一圈的情况

先见电机内部齿轮示意图9-7。

上面讲八节拍模式下转动一圈需要64节拍。实际这转动一圈指的是内部最小的齿轮转动一圈需要的节拍数,外部转轮转动一圈需要的节拍数还需要根据电机减速比参数计算。见表9-2中,28BYJ-48电机减速比为1:64。但因为该电机应用在消费领域,所以该参数表也只是给了一个近似整数的减速比1:64,一般转动角度不超过360度。这就不会导致太大误差。随着转动圈数的增多,误差会发生质变。现在通过计算实际减速比约为1:63.684。这就得出八节拍模式下外部转轮转动一圈需要约4076(64 x 63.684)节拍 。


4、综合小程序–按键控制电机转动

//综合小程序-按键控制步进电机的转动

#include


sbit keyin1 = P2^4;

sbit keyin2 = P2^5;

sbit keyin3 = P2^6;

sbit keyin4 = P2^7;

sbit keyout1 = P2^3;

sbit keyout2 = P2^2;

sbit keyout3 = P2^1;

sbit keyout4 = P2^0;


unsigned char keysta[4][4]= { //记录全部矩阵按键当前状态

{1,1,1,1}, {1,1,1,1},{1,1,1,1},{1,1,1,1}

};


unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表

    { 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键

    { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键

    { 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键

    { 0x30, 0x1B, 0x0D, 0x27 }  //数字键0、ESC键、  回车键、 向右键

};


signed long beats = 0;电机转动节拍总数


void KeyDriver(); //按键驱动函数

void KeyAction(unsigned char keycode);按键动作函数

void StarMotor(signed long angle);//步进电机启动函数

void StopMotor(); //步进电机停止函数

void KeyScan(); //按键扫描函数

void TurnMotor();//电机转动控制函数


void main()

{

EA = 1;//使能总中断

TMOD = 0x01;//为T0配置模式1

TH0 = 0xFC;//为T0赋初值0xFC67,定时1ms

TL0 = 0x67;

TR0 = 1;  //开启T0

ET0 = 1; //使能T0中断


while(1)

{

KeyDriver(); //调用按键驱动函数

}

}


//按键驱动函数,检测按键动作,调用相应动作函数,需要在主循环中调用

void KeyDriver()

{

unsigned char i, j;

static unsigned char backup[4][4]= { //按键值备份,保存前一次的值

{1,1,1,1}, {1,1,1,1}, {1,1,1,1}, {1,1,1,1}

};

for(i = 0; i < 4; i++) //循环检测4*4的矩阵按键

{

for(j = 0; j < 4; j++)

{

if(backup[i][j] != keysta[i][j])//检测按键动作

{

if(backup[i][j] == 0)  //按键前次值为0执行动作

{

KeyAction(KeyCodeMap[i][j]);//调用按键动作函数

}

backup[i][j] = keysta[i][j];//刷新前一次的备份值

}

}

}

}


//按键动作函数,根据键码执行相应的操作,keycode为按键键码

void KeyAction(unsigned char keycode)

{

static unsigned char dirMotor = 0; //电机转动方向

if((keycode >= 0x30) && (keycode <= 0x39))//控制电机转动1~9圈

{

if(dirMotor == 0)

{

StarMotor(360*(keycode - 0x30));

}

else

{

StarMotor(-360*(keycode - 0x30));

}

}

else if(keycode == 0x26) //向上键,控制转动方向为正转

{

dirMotor = 0;

}

else if(keycode == 0x28)//向下键,控制转动方向为反转

{

dirMotor = 1;

}

else if(keycode == 0X25)  //向左键,固定正转90度

{

StarMotor(90);

}

else if(keycode == 0x27) //向右键,固定反转90度

{

StarMotor(-90);

}

else if(keycode == 0x1B) //esc键,停止转动

{

StopMotor();

}

}

//步进电机启动函数,angle为需要转动的角度

void StarMotor(signed long angle)

{

EA = 0;

beats = (angle*4076)/360;  //实测为4076拍转动一圈

EA = 1;

}

//步进电机停止函数

void StopMotor()

{

EA = 0;

beats = 0;

EA = 1;

}


//T0中断服务函数,用于按键扫描与电机转动控制

void InterruptTimer0() interrupt 1

{

static bit div = 1;

TH0 = 0xFC; //重新加载初值

TL0 = 0x67;

KeyScan(); //执行按键扫描

//用一个静态bit变量实现二分频,即定时2ms,用于控制电机

div = ~div;

if(div == 1)

{

TurnMotor();

}

}


void KeyScan()

{

unsigned char i;

static unsigned char keyout = 0;//矩阵按键扫描输出索引

static unsigned keybuf[4][4] = { //矩阵按键扫描缓冲区

{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},

{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF}

};

//将一行的4个按键值移入缓冲区

keybuf[keyout][0] = (keybuf[keyout][0] << 1) | keyin1;

keybuf[keyout][1] = (keybuf[keyout][1] << 1) | keyin2;

keybuf[keyout][2] = (keybuf[keyout][2] << 1) | keyin3;

keybuf[keyout][3] = (keybuf[keyout][3] << 1) | keyin4;

//消抖后更新按键状态

for (i = 0; i < 4; i++)//每行四个按键,所以循环4次

{

if( (keybuf[keyout][i] & 0x0F) == 0x00 )

{ //连续4次扫描值为零,即4*4ms内都是按下状态,可认为按键已稳定地按下

keysta[keyout][i] = 0;

}

if( (keybuf[keyout][i] & 0x0F) == 0x0F )

{ //连续4次扫描值为1,即4*4ms内都是弹起状态,可认为按键已稳定地弹起

keysta[keyout][i] = 1;

}

}

keyout++; //输出索引递增

keyout = keyout & 0x03; //索引值加到4后归零

switch(keyout)   //根据索引,释放当前输出引脚,拉低下次的输出引脚

{

case 0:keyout4 = 1; keyout1 = 0;break;

case 1:keyout1 = 1; keyout2 = 0;break;

case 2:keyout2 = 1; keyout3 = 0;break;

case 3:keyout3 = 1; keyout4 = 0;break;

default: break;

}

}


//电机控制函数

void TurnMotor()

{

unsigned char tmp;//临时变量

static unsigned char index = 0; //节拍输出索引

unsigned char code BeatCode[8] = {//步进电机节拍对应的IO控制代码

0x0E, 0x0C, 0x0D, 0x09, 0x0B, 0x03, 0x07, 0x06

};

if(beats != 0)//节拍数不为0则产生一个驱动节拍

{

if(beats > 0)//节拍数大于0时正转

{

index++; //正转时节拍输出索引递增

index = index & 0x07;//用&操作实现到8归零

beats--;//正转时节拍数递减

}

else //节拍数小于零时反转

{

index--;//正转时节拍输出索引递减

index = index & 0x07; //用&操作实现到-1时归7

beats++;//正转时节拍数递减

}

tmp = P1;//用tmp把P1口当前值暂存

tmp = tmp & 0xF0;//用&操作清空低四位

P1 = tmp | BeatCode[index];//用|操作把节拍代码写到低四位并送到P1

}

else  //节拍数为零则关闭步进电机所有相

{

P1 = 0xFF;

}

}


因为STC89C52是8位单片机,单片机操作数据时都是按8位即一个字节进行的,操作多个字节数据,无论读还是写就必须分次进行了,所以程序中计算unsigned long型变量beats时,为了防止beats变量在一个一个字节赋值时,突然进入中断,造成beats数值错误,就在进行beats变量赋值前,关闭中断,在赋值后重新打开中断,这就避免了中断的发生。


5、蜂鸣器

蜂鸣器按驱动方式分为:有源蜂鸣器和无源蜂鸣器,

有源蜂鸣器:内部带了振荡源,给了BUZZ引脚一个低电平,就会响

无源蜂鸣器:内部带无振荡源,要让它响要给予500Hz ~ 4.5KHzz之间的脉冲频率信号来驱动它。


下面见kst-51开发板中的蜂鸣器电路图

说明:蜂鸣器驱动电流相对较大,因此需要三极管驱动。因为蜂鸣器是感性器件,导通时蜂鸣器电流逐渐变大,关闭后需要续流二极管D4来避免蜂鸣器的电感电流造成的反向冲击。根据电路分析Buzz引脚位于P1.6,那么发声程序就很好编写了。


6、蜂鸣器发声程序

#include


sbit Buzz = P1^6;//蜂鸣器控制引脚


unsigned char  TORH;  //T0重载值的高字节

unsigned char  TORL;  //T0重载值的低字节


void OpenBuzz(unsigned int frequ);

void StopBuzz();


void main()

{

unsigned int i;

EA = 1; //使能总中断

TMOD = 0x01; //配置T0为模式1,但先不启动


while(1)

{

OpenBuzz(4000);//以4k的频率启动蜂鸣器

for(i = 40000; i > 0; i--);//非精准延时蜂鸣器

StopBuzz();//停止蜂鸣器

for(i = 40000; i > 0; i--);

OpenBuzz(1000);//以1kHZ的频率启动蜂鸣器

for(i = 40000; i > 0; i--);

StopBuzz();//停止蜂鸣器

for(i = 40000; i > 0; i--);

}

}  

//蜂鸣器启动函数,frequ-工作频率


void OpenBuzz(unsigned int frequ)

{

unsigned int reload;//计算所需的定时器重载值

reload = 65536 - (11059200 / 12)/(frequ*2); //由给定频率计算定时器重载值

TORH = (unsigned char)(reload >> 8);//16位重载值分解为高低两个字节

TORL = (unsigned char)reload;

TH0 = 0xFF;//设定一个即将溢出的初值,使定时器马上投入工作

TL0 = 0xFE;

ET0 = 1;//使能T0中断

TR0 = 1;//启动T0


}

//蜂鸣器停止函数

void StopBuzz()

{

ET0 = 0;//禁用T0中断

TR0 = 0;//停止T0

}


//T0中断服务函数,用于控制蜂鸣器发声

void InterruptTimer0() interrupt 1

{

TH0 = TORH;//重新加载重载值

TL0 = TORL;

Buzz = ~Buzz;//反转蜂鸣器控制电平

}

推荐阅读

史海拾趣

Electron Products Inc公司的发展小趣事

EPI一直非常重视产品的品质管理。公司建立了严格的质量管理体系,从原材料采购到产品生产、检测、包装等各个环节都进行严格把控。此外,EPI还注重持续改进,不断引入先进的生产技术和设备,提升产品的质量和性能。这些举措使得EPI的产品在市场上享有很高的声誉和口碑。

AMOTECH(阿莫泰克)公司的发展小趣事

1994年,AMOTECH在韩国创立,凭借创始人的远见卓识和技术团队的扎实能力,公司迅速在电子行业中崭露头角。经过两年的努力,1996年,AMOTECH被政府通讯部评为“光明前途企业”,这是对其技术实力和市场潜力的肯定。随后,公司不断加大研发投入,终于在2000年获得ISO9000认证,这标志着AMOTECH在产品质量管理上达到了国际标准。

德尔创(Dersonic)公司的发展小趣事

面对不断变化的市场环境和客户需求,德尔创始终坚持可持续发展的理念。公司注重环境保护和资源节约,积极推行绿色生产和循环经济。同时,德尔创还加强了内部管理和团队建设,通过优化流程和提高效率来降低成本和提升效益。对于未来,德尔创已经制定了明确的发展规划和目标,将继续加大在技术研发、市场拓展和品牌建设等方面的投入力度,努力成为全球电子元器件行业的领军企业之一。

Crosspoint Solutions公司的发展小趣事

随着技术的不断更新换代,人才成为电子企业竞争的核心要素。Crosspoint Solutions公司高度重视人才培养和引进工作,通过校园招聘、社会招聘等多种渠道吸引优秀人才加入。同时,公司还建立了完善的培训体系,不断提升员工的技能水平和创新能力。这些优秀的人才为公司的发展提供了强有力的支撑。

American Power Management Inc公司的发展小趣事

随着电子行业的快速发展,新技术不断涌现,市场竞争也日趋激烈。面对这一变革,APMI及时调整战略,加大研发投入,紧跟技术潮流。公司不仅推出了多款具有竞争力的新产品,还积极拓展新的应用领域,如新能源汽车、物联网等。通过不断创新和拓展,APMI成功应对了行业变革带来的挑战,保持了持续稳健的发展态势。

Cembre SPA公司的发展小趣事

Cembre SPA一直秉持品质至上的原则,不断追求产品质量的提升。公司建立了严格的质量管理体系,从原材料采购到生产制造,再到产品出厂,每一个环节都严格把控。同时,公司还注重持续改进,通过引入先进的生产设备和技术,不断提高生产效率和产品质量。

问答坊 | AI 解惑

用SPMC75F2313A实现LIN结点

1 引言    LIN 是低成本网络中的汽车通讯协议标准,LIN(Local Interconnect Network)是低成本的汽车网络,它是现有多种汽车网络在功能上的补充由于能够提高质量、降低成本,LIN 将是在汽车中使用汽 ...…

查看全部问答>

做个FDD接口的U盘如何?

昨日与友人闲谈,得知其急需一FDD接口的U盘.用于工控.遂发此贴,求助于诸位.提及FDD(即软驱),众皆笑曰:\"淘汰久矣!\"然,君不见其依然服役于众多工控场合?随之FPGA/RAM等先进技术之普及.待处理数据之大,昔日之1.44何以满足?市有产品曰:仿真软驱,价格奇 ...…

查看全部问答>

在Keil里出现Syntax error

在Keil里出现Syntax  error怎样解决…

查看全部问答>

应届生请教,WINCE嵌入式应用编程发展前景,请大家谈谈个人对现在工作的满意度?

想请教下wince、windows mobile编程方面的工作前景怎样呢》?高薪的可能性? 上次跟一个同学谈过,说这方面可能比较难拿到高薪 不知道大家的情况怎样呢?或者谈谈个人对现在工作的满意度? 下面介绍下我自己的基本情况 我是应届研究生,熟 ...…

查看全部问答>

老妪变少女,AMD暴笑视频

       偶然在网上看到了AMD的一个“我为三核狂”活动,整个活动的主旨都是围绕“三核”的概念来的,网友的热情和创意也是让人叹为观止,大家下面这些有趣的作品吧。简直是神了!大家也来欣赏一下哦      &n ...…

查看全部问答>

STM32系列芯片名称定义

每种STM32的产品都由16个字母或数字构成的编号标示,用户向ST订货时必须使用这个编号指定需要的产品。这16个字符分为8个部分,下面通过一个例子说明它们的意义:      STM32 F 103 C 6 T 7 xxx        1   2& ...…

查看全部问答>

mc1496

本帖最后由 paulhyde 于 2014-9-15 09:22 编辑 这三个电解电容怎么连接,求高手指导  …

查看全部问答>

【Energia开发环境】MSP430 LAUNCHPAD学习笔记2--Lab2 KEY control LED1

【Energia开发环境】MSP430 LAUNCHPAD学习笔记2--Lab2 KEY control LED1材料:MSP430 LAUNCHPAD x 1LED1(P1.0)KEY(P1.3) 实验目的:让MSP430 LAUNCHPAD的P1.0 Y有按键S2控制亮灭原理图如下: 原理分析:为保持按键在没有按下时,P1.3引脚保持高电 ...…

查看全部问答>

红外光通信装置

13年全国大学生电子设计的题目,请问谁可以共享一下资料,能清晰的看清的那种哦,非常感谢。 …

查看全部问答>

CCS怎么使用STLINK

学校为了省钱,没有购买开发板,而是购买的芯片STLINK仿真器。有谁在CCS下用过stlink,在CCS的CONECTION选项下没有STlink,那个大神能否告知一下 …

查看全部问答>