完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
`````` 本帖最后由 friend0720 于 2016-9-23 10:18 编辑 前言 单片机是一门综合技术,它要求学习者具有一定的电子电路基础,和一定的 C 语言或汇编语言基础。当然如果你学习过《微机原理》那就更好了。C 语言是目前单片机开发最常用到的开发语言,因此请务必学好 C 语言。 同时单片机又是一门实践性很强的技术,如果不亲自动手搭建电路编写程序,是很难真正学会单片机的。下面说说单片机学习的主要过程: 1. 确定一款单片机作为自己的学习目标。目前主流8位单片机有stm8、AVR、PIC等。 2. 搜集该型单片机的各种学习资料。比如书籍、论坛帖子、视频教程等。 3. 下载并搭建软件开发环境 4. 购买硬件开发工具、烧录器、调试器、各种元器件。搭建单片机最小系统,编写程序驱动各种片内资源。 5. 扩展外围电路,并为之编写驱动程序。 后续本人将以ATmega16单片机为例,介绍具体的学习过程。下面是未来我们开发板的大致模样。
送给初学者的一句话:“勿在浮沙筑高台” 遥远的海 (待续) 附件加密!请勿下载! ``````
评分
|
||
相关推荐
715 个讨论
|
||
|
|
|
|
|
|
|
|
|
|
本帖最后由 friend0720 于 2015-7-28 08:55 编辑
cheng6626 发表于 2015-7-27 14:45 少个分号。。。。。。。。。。。。。。。。 |
|
|
|
|
|
|
|
|
第16节直流电机测速 上一节简单介绍了步进电机,本节介绍直流电机光电测速方法。要想知道电机转速,只要数出电机1秒钟转了多少圈就可以了,不过很显然我们无法用眼睛完成这个任务。但是聪明的灵长类动物想出了使用光电开关测量电机转速的方法。 16.1 透射式光电测速原理 透射式光耦由两部分组成,一部分时发光二极管,发射红外线,另一部分是红外接收管,中间缝隙为光线传输而设。 外围电路如下图所示,发射电路加200欧母限流电阻,接收端加10K上拉电阻。信号经非门后输出,非门的作用是波形整形并提高驱动能力。 当没有障碍物遮挡时,光电管接收到光线,饱和导通,C极为低电平,经74ls14非门后,信号变为高电平; 当电机的光电编码盘不透光部分挡住时,光电管截止,C极为高电平,经74ls14非门后,信号变为低电平; 这样,每个缝隙经过时都会产生一个脉冲,只要使用单片机对单位时间内脉冲计数,就可以计算出电机转速。 16.2 原理图 原理图比较简单。 ITR9608光电开关信号输出到74LS14第1脚,经非门反向后由第2脚输出到单片机PD6脚。PD6是Atmega16的输入捕获管脚,通过PD6捕获输入脉冲,从而计算出电机转速。 我们使用S8550三极管驱动5V直流电机,单片机PD7脚通过一个1K电阻接S8550基极,低电平时,电机转动。哥曾经因为忘记串接1K限流电阻,让两个S8550升起了蘑菇云。 16.3 实物图 绿线接PD6,白线接PD7。红线接5V,剩下那根接地。 于是哥又购买了图中左下角那个电机,不过买回来一看,发现没有合适的接线端子,又不舍得暴力破坏,只好暂时放到一边。 没办法,哥只好拿起碳素笔,给之前那个电机的码盘化了化妆。于是它就变成了下面那个样子。虽然精度不高,但却勉强可用,凑合了! 16.4 实测结果 电机转速稳定后,实测电机每分钟转速有上下5圈内的波动。这可能是因为码盘精度不高造成的。 16.5 程序及说明
“勿在浮沙筑高台” 遥远的海 (待续) |
|
|
|
|
|
|
|
|
程序修改完了,有些注释忘了修改!!!!!!
|
|
|
|
|
|
|
|
|
程序修改完了,有些注释忘了修改!!!!!!
|
|
|
|
|
|
|
|
|
好像论坛服务器有问题
|
|
|
|
|
|
|
|
|
顶个。。。。。。。。
|
|
|
|
|
|
|
|
|
谢谢楼主的帖子,学习了
|
|
|
|
|
|
|
|
|
本帖最后由 friend0720 于 2016-2-25 20:33 编辑 第17节 PWM直流电机调速 17.1 直流电机转速 根据直流电机转速计算公式:n=(U-RI)/Ceφ,其中U为电枢电压;R为电枢回路电阻;I为电枢电流;φ为电动机气隙主磁通;Ce为常数,与电动机结构相关。所以影响直流电机转速的是电枢电阻R、气隙主磁通φ及电枢电压三个因素。 所以一般直流电机调速有调节电枢电阻、调节励磁电流和调节电枢电压三种方式。 17.2 PWM直流电机调速 既然通过调节电枢电压就可以调节直流电机转速,那么调节电机转速问题就转换为调节电枢电压的问题。那么我们又如何对电枢电压进行控制呢?答案就是PWM。我们通过调节PWM方波占空比,就可以控制电枢有效电压。这样调节转速的问题就转换成调节PWM方波占空比的问题。 17.2 Atmega16 PWM Atmega16单片机T/C2(定时/计数器2)可以输出PWM方波,而且通过改变OCR2寄存器的值,就可以改变PWM方波占空比。T/C2 PWM又两种模式:快速PWM模式、相位修正PWM模式。这里使用相位修正PWM模式。 相位修正PWM 模式(WGM21:0 = 1) 为用户提供了一个获得高精度相位修正PWM 波形 的方法。此模式基于双斜坡操作。计数器TCNT2重复地从0 计到255,然后又从255 倒退回到0。在一般的比较输出模式下,当TCNT2往255计数时若发生了TCNT2 于OCR2的匹配,OC2(PD7)将清零为低电平;而在TCNT2往0计数时若发生了TCNT2 于OCR2 的匹配,OC2(PD7)将置位为高电平。工作于反向输出比较时则正好相反。与单斜坡操作相比,双斜坡操作可获得的最大频率要小。但由于其对称的特性,十分适合于电机控制。 17.3 原理图 原理图同上节(直流电机测速) 17.4 实测结果 17.5 程序及说明 /* ----------------------------------------------------------------------------------------- 工程: Test系列工程 环境: AVR Studio4.17 + WinAVR2010 设备: Atmega16 作者: 遥远的海 日期: 2015-08-01 说明: 输入捕获之电机测速 PWM电机调速 PD6 输入捕获,用来测量电机转速 PD7 启动、停止电机(低电平电机转动,高电平电机停转) ----------------------------------------------------------------------------------------- */ #include #include //--------------------------- //数据类型 //--------------------------- typedef unsigned char U8; typedef signed char S8; typedef unsigned int U16; typedef signed int S16; typedef unsigned long U32; //--------------------------- //电机控制IO 占用PD7(21)脚 //--------------------------- #define MOTO_BIT 0x80 #define MOTO_Init() DDRD |= MOTO_BIT //配置 PD7 口为输出 //--------------------------- //总中断 //--------------------------- #define EN_INT() sei() //开中断 #define DS_INT() cli() //关中断 //串口发送标志 volatile U8 m_ucFlag=0; //输入捕获时间印记 volatile U32 m_ulICR=0; /* ----------------------------------------------------------------------------------------- 马达初始化函数 PD6 输入捕获,用来测量电机转速 PD7 OC2,T/C2 PWM 输出(低电平电机转动,高电平电机停转) 使用28线测速码盘 ----------------------------------------------------------------------------------------- */ void Moto_Init(void) { //-------------------------------------- //T/C2 PWM ,转速控制 //-------------------------------------- //要想在引脚上得到输出信号必须将 OC2 的数据方向设置为输出 //配置 PD7 口为输出 MOTO_Init(); TCCR2=0; //16MHz 时钟32分频(2us) //8位计数器最大计数周期=255*2us 约为0.5ms //因为相位PWM频率是计数器溢出频率0.5倍 //所以相位PWM模式下,PWM频率约为1KHz。 TCCR2 |= (0< //波形产生模式:相位PWM TCCR2 |= (0< //比较输出模式: //在升序计数时发生比较匹配将置位OC2 ; //降序计数时发生比较匹配将清零OC2。 //我的电机控制口低电平转动 TCCR2 |= (1< //可以通过调节OCR2值来调节占空比。 //初始占空比128/255=50%(对我来说其实是空占比 OCR2/255)。 OCR2=128; //-------------------------------------- //T/C1 输入捕获,电机测速 //-------------------------------------- //PD6 (ICP1 单片机第20脚) 配置为输入 DDRD &=~(1< //PD6 上拉电阻 PORTD|= (1< //Bit 7 – ICNC1: 入捕捉噪声抑制器 //Bit 6 – ICES1: 输入捕捉触发沿选择 0下降沿触发,1上升沿触发 //Bit 2:0 – CS1 2:0: 时钟选择 //使能输入捕获噪声抑制 //初始设置为下降沿触发 //时钟分频 8 (16M外部时钟下0.5微秒计数一次) TCCR1B|=0B10000010; //T/C1 输入捕捉中断使能 TIMSK|= 1< } /* ----------------------------------------------------------------------------------------- 定时器1输入捕获中断,计数周期0.5微秒。 TCCR1B&=~0x40; 下降沿触发 TCCR1B|=0x40; 上升沿触发 我的电机测速码盘是 28线,精度不高,因此测量一周计数时间。 ----------------------------------------------------------------------------------------- */ ISR(SIG_INPUT_CAPTURE1) { static U8 ucStep; U16 usICR; //保存时间印记 usICR=ICR1; //清零计数器 TCNT1 = 0; switch(ucStep) { //第1个下降沿 case 0: m_ulICR=0; ucStep++; break; //第29个下降沿,整好转一周 case 28: m_ulICR+=usICR; //串口发送标志 m_ucFlag=1; ucStep=0; break; default: m_ulICR+=usICR; ucStep++; break; } return; } /* ----------------------------------------------------------------------------------------- USART ----------------------------------------------------------------------------------------- */ #define UART_BUF_LEN 5 //串口发送缓存长度 #define UART_TIME_OUT 500 //超时控制 //串口发送缓存 static U8 m_SndBuf[UART_BUF_LEN]; static U8 *pSnd; static U8 *pSnE; //发送缓存尾部 /* ----------------------------------------------------------------------------------------- USART发送完中断,每发送完一个字符产生一次中断 ----------------------------------------------------------------------------------------- */ ISR(SIG_UART_TRANS) { if(pSnd { UDR=*pSnd++; } else pSnd=m_SndBuf; } /* ----------------------------------------------------------------------------------------- 串口初始化 115200 8 N 1 ----------------------------------------------------------------------------------------- */ void UART_Init(void) { pSnd=m_SndBuf; pSnE=pSnd+UART_BUF_LEN; DDRD|=(1< //先关闭串口所有收发功能 UCSRB=0x00; UCSRA=0x00; //帧格式 8 N 1 UCSRC= (1<
//波特率设置 fosc = 16.0000 MHz,115200 ,UBRR=8 UBRRH=0x00; UBRRL=0x08; //使能管脚串口功能,使能发送中断 UCSRB=(1<
} /* ----------------------------------------------------------------------------------------- 发送数据,将数据缓存 m_SndBuf[]中 pSnd到pSnE之间的数据发送出去 ----------------------------------------------------------------------------------------- */ void UART_Write(void) { U16 timeOut=UART_TIME_OUT; //等待发送完成 while(!(UCSRA&(1< { //超时控制 if(--timeOut==0) return ; } //将数据发送出去 UDR=*pSnd++; } /* ----------------------------------------------------------------------------------------- 函数: main 功能: C 语言主函数 入口: void 出口: int 备注: 电机每秒转速==1000000(us)/(m_ulICR*0.5(us))==2000000(us)/(m_ulICR)) 电机每分钟转速==120000000/m_ulICR ----------------------------------------------------------------------------------------- */ int main(void) { U16 usSpeed=0; float fSpeed=0; Moto_Init(); UART_Init(); EN_INT(); //开全局中断 while(1) { if(m_ucFlag) { //计算电机每分钟转速 fSpeed=(float)(120000000/(m_ulICR)); usSpeed=(U16)(fSpeed); //发送数据到串口 m_SndBuf[0]=0xF5; m_SndBuf[1]=(U8)usSpeed; m_SndBuf[2]=(U8)(usSpeed>>8); m_SndBuf[3]=m_SndBuf[1]^m_SndBuf[2]; m_SndBuf[4]=0xF5; //发送指针指向发送缓存头部 pSnd=m_SndBuf; //数据尾指针 pSnE=pSnd+UART_BUF_LEN; //数据将在发送中断中全部自动发送。 UART_Write(); } m_ucFlag=0; } return 0; } “勿在浮沙筑高台” 遥远的海 (待续) |
|
|
|
|
|
|
|
你正在撰写讨论
如果你是对讨论或其他讨论精选点评或询问,请使用“评论”功能。
384 浏览 0 评论
398 浏览 0 评论
405 浏览 0 评论
780 浏览 0 评论
RT-Thread与英飞凌(infineon)合作得板子PSOC 6 板子学习
741 浏览 0 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
17000 浏览 31 评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-11 20:32 , Processed in 1.617499 second(s), Total 77, Slave 69 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
13528