历史上的今天
返回首页

历史上的今天

今天是:2024年11月09日(星期六)

正在发生

2019年11月09日 | 51单片机+编码器+42步进电机的源程序

2019-11-09 来源:51hei

前几天帮别做一个51的小东西需要编码器,结果发现网上编码器的程序比较不好找,自己根据别人一个巧妙的思路写了一个读编码器读数的程序,用LCD1602显示出来。里边还有使用L298N驱动42步进电机部分,可以参考一下。

单片机源程序如下:

#include


typedef unsigned char uchar;

typedef unsigned int uint;


//LCD1602定义

#define LCD1602_DB P0        //LCD1602数据总线


sbit LCD1602_RS = P2^7;         //RS端

sbit LCD1602_RW = P2^6;         //RW端

sbit LCD1602_EN = P2^5;         //EN端


uchar code digit[ ]={"0123456789"}; //定义字符数组显示数字

uchar idata TEST[]="TEST";


//电机正反转二维数组 0为逆时针,1为顺时针

uchar code MotorCode[2][8]={{0x04,0x06,0x02,0x0a,0x08,0x09,0x01,0x05},{0x05,0x01,0x09,0x08,0x0a,0x02,0x06,0x04}};


uchar MotorStatus;//电机正反转标志位


sbit EncoderA=P3^2;    //编码器A相

sbit EncoderB=P3^4;                 //编码器B相


uint EncoderCount=0 ;

/* 毫秒软件延时函数*/

void delay_ms(uint x)

{

        uint a,b;

        for(a=x;a>0;a--)

                for(b=114;b>0;b--); 

}


/*=================================================

*函数名称:Read_Busy

*函数功能:判断1602液晶忙,并等待

=================================================*/

void Read_Busy()

{

        uchar busy;

        LCD1602_DB = 0xff;//复位数据总线

        LCD1602_RS = 0;          //拉低RS

        LCD1602_RW = 1;          //拉高RW读

        do

        {

                LCD1602_EN = 1;//使能EN

                busy = LCD1602_DB;//读回数据

                LCD1602_EN = 0;         //拉低使能以便于下一次产生上升沿

        }while(busy & 0x80); //判断状态字BIT7位是否为1,为1则表示忙,程序等待

}

/*=================================================

*函数名称:LCD1602_Write_Cmd

*函数功能:写LCD1602命令

*调用:Read_Busy();

*输入:cmd:要写的命令

=================================================*/

void LCD1602_Write_Cmd(uchar cmd)

{

        Read_Busy();         //判断忙,忙则等待

        LCD1602_RS = 0;

        LCD1602_RW = 0;        //拉低RS、RW操作时序情况1602课件下中文使用说明基本操作时序章节

        LCD1602_DB = cmd;//写入命令

        LCD1602_EN = 1;         //拉高使能端 数据被传输到LCD1602内

        LCD1602_EN = 0;         //拉低使能以便于下一次产生上升沿

}

/*=================================================

*函数名称:LCD1602_Write_Dat

*函数功能:写LCD1602数据

*调用:Read_Busy();

*输入:dat:需要写入的数据

=================================================*/

void LCD1602_Write_Dat(uchar dat)

{

        Read_Busy();

        LCD1602_RS = 1;

        LCD1602_RW = 0;

        LCD1602_DB = dat;

        LCD1602_EN = 1;

        LCD1602_EN = 0;

}

/*=================================================

*函数名称:LCD1602_Clear

*函数功能:LCD1602清屏

=================================================*/

void LCD1602_Clear()

{

        Read_Busy();

        LCD1602_Write_Cmd(0x01); //清屏

}



/*=================================================

*函数名称:LCD1602_Dis_OneChar

*函数功能:在指定位置显示一个字符

*调用:LCD1602_Write_Cmd(); LCD1602_Write_Dat();        

*输入:x:要显示的横坐标取值0-40,y:要显示的行坐标取值0-1(0为第一行,1为第二行)

                dat:需要显示的数据以ASCLL形式显示

=================================================*/

void LCD1602_Dis_OneChar(uchar x, uchar y,uchar dat)

{

        if(y)        x |= 0x40;

        x |= 0x80;

        LCD1602_Write_Cmd(x);

        LCD1602_Write_Dat(dat);                

}

/*=================================================

*函数名称:LCD1602_Dis_Str

*函数功能:在指定位置显示字符串

*调用:LCD1602_Write_Cmd(); LCD1602_Write_Dat();

*输入:x:要显示的横坐标取值0-40,y:要显示的行坐标取值0-1(0为第一行,1为第二行)

                *str:需要显示的字符串

=================================================*/

void LCD1602_Dis_Str(uchar x, uchar y, uchar *str)

{

        if(y) x |= 0x40;

        x |= 0x80;

        LCD1602_Write_Cmd(x);

        while(*str != '')

        {

                LCD1602_Write_Dat(*str++);

        }

}

/*=================================================

*函数名称:Init_LCD1602

*函数功能:1602初始化

*调用:        LCD1602_Write_Cmd();

=================================================*/

void Init_LCD1602()

{

        LCD1602_Write_Cmd(0x38); //        设置16*2显示,5*7点阵,8位数据接口

        LCD1602_Write_Cmd(0x0c); //打开显示屏,不显示光标,光标所在位置的字符不闪烁。

        LCD1602_Write_Cmd(0x06); //读写一字节后地址指针加1

        LCD1602_Write_Cmd(0x01); //清除显示

}


void Motor_Forward() //电机正转

{

        TMOD=0x01;

        TH0=(65535-2000)/256;

        TL0=(65535-2000)%256;

        EA=1;

        ET0=1;

        TR0=1;

        MotorStatus=0;

}

void Motor_Reversal() //电机反转

{

        TMOD=0x01;

        TH0=(65535-2000)/256;

        TL0=(65535-2000)%256;

        EA=1;

        ET0=1;

        TR0=1;

        MotorStatus=1;

}


void Motor_Stop()  //停止电机

{

        ET0=0;

        TR0=0;

        P1=P1&0xF0;

}



uchar index = 0;  //定义节拍输出索引

void time0() interrupt 1

{

        uchar tmp;  //定义一个临时变量


        TH0=(65535-1000)/256;

        TL0=(65535-1000)%256;

        

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

  tmp = tmp & 0xF0; //用&操作清零低4位

        //用|操作把节拍代码写到低4位

  tmp = tmp | MotorCode[MotorStatus][index];

        //把低4位的节拍代码和高4位的原值送回 P1

  P1 = tmp;

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

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

        

}


Init_Encoder ()

{

        EA = 1;        //开总中断

        EX0 = 1;//开外部中断1

        IT0 = 1;//外部中断1下降沿触发

}




void main()

{

        Init_Encoder ();

        Init_LCD1602();

        Motor_Reversal();  

        LCD1602_Dis_Str(0, 0, &TEST[0]);                                                                                //提示第一行MENU1        

    while (1)

                {

                        LCD1602_Dis_OneChar(0,1,digit[EncoderCount/10000]);

                        LCD1602_Dis_OneChar(1,1,digit[EncoderCount%10000/1000]);

                        LCD1602_Dis_OneChar(2,1,digit[EncoderCount%1000/100]);

                        LCD1602_Dis_OneChar(3,1,digit[EncoderCount%100/10]);

                        LCD1602_Dis_OneChar(4,1,digit[EncoderCount%10/1]);

                        delay_ms(100);

//      delay_ms(500);  //延时 2 ms,即 2 ms 执行一拍

//                        Motor_Reversal(); //电机反转

//                        delay_ms(500);  //延时 2 ms,即 2 ms 执行一拍

//                        Motor_Stop();

//                        delay_ms(500);  //延时 2 ms,即 2 ms 执行一拍

    }

        

}


//外部中断1中断服务程序

void int0() interrupt 0

{

        if (EncoderB)

        {

                EncoderCount++;     //正转

        }else

        {

                EncoderCount--;     //反转

        }

        if (EncoderCount==360)

        Motor_Stop();        

}  



推荐阅读

史海拾趣

Furukawa Electric Co Ltd公司的发展小趣事

Furukawa Electric Co., Ltd. 在电子行业的五个发展故事

故事一:创立与早期发展

Furukawa Electric Co., Ltd.(简称“Furukawa Electric”或“古河电工”)的故事始于1884年,当时公司在日本东京建立了铜精炼设施和线缆加工工厂。这一初期的发展奠定了公司在电线电缆领域的坚实基础。随着工业革命的推进,对通信和电力传输的需求日益增长,Furukawa Electric凭借其精湛的技艺和高质量的产品逐渐在市场中站稳脚跟。通过不断的技术创新和产品优化,公司逐渐扩大了其业务范围,涉足电信、电子产品、汽车等多个领域。

故事二:技术创新与领先地位

在20世纪,Furukawa Electric成为了新技术领域的先驱。公司不仅在传统的电线电缆领域保持领先地位,还积极投入研发,开发出了许多具有划时代意义的产品。例如,在光通信领域,Furukawa Electric致力于推动“光纤到户(FTTH)”工程,为信息化社会提供了重要的技术支持。此外,公司在半导体领域也取得了显著成就,开发了多种先进的电子元件和散热产品,满足了市场对高性能电子产品的需求。

故事三:汽车领域的深入合作

近年来,Furukawa Electric进一步扩展了其业务范围,与多家汽车制造商建立了紧密的合作关系。特别是在电动汽车领域,公司凭借其先进的高压绕组线(HVW)技术,为汽车制造商提供了高性能的电动机解决方案。这些绕组线不仅满足了电动汽车对更轻盈、更薄的电动机绕组线及更高电压的需求,还提升了电动机的整体性能。通过与Superior Essex Inc.的合资企业“Essex Furukawa Magnet Wire Europe GmbH”,Furukawa Electric成功将这一技术引入欧洲市场,进一步巩固了其在全球汽车行业的领先地位。

故事四:全球市场的拓展

随着全球化的加速推进,Furukawa Electric也加快了其全球市场的拓展步伐。公司在全球范围内建立了完善的生产和销售网络,覆盖了亚洲、欧洲、美洲等多个地区。通过与国际知名企业的合作与竞争,Furukawa Electric不断提升自身的技术实力和市场竞争力。同时,公司还积极参与国际标准的制定和推广工作,为全球电子行业的发展做出了重要贡献。

故事五:可持续发展与社会责任

在追求经济效益的同时,Furukawa Electric也始终关注可持续发展和社会责任。公司致力于通过技术创新和产品优化来降低能耗和减少环境污染。例如,在电力传输系统和配电电缆领域,Furukawa Electric开发出了多种高效节能的产品,满足了市场对绿色、环保产品的需求。此外,公司还积极参与社会公益活动,为当地社区的发展贡献自己的力量。这些举措不仅提升了公司的社会形象,也为其在电子行业的长期发展奠定了坚实的基础。

超音(CY)公司的发展小趣事

随着科技的不断进步,超音意识到技术创新对于公司发展的重要性。因此,公司加大了研发投入,积极引进高端人才,不断推出具有创新性和竞争力的产品。其中,超音的一款高端音响产品凭借其卓越的音质和精美的外观设计,在市场上获得了广泛的好评。此外,超音还积极与其他科技公司合作,共同研发新产品,不断拓宽产品线。

兵字(BingZi)公司的发展小趣事

随着公司规模的不断扩大和产品线的日益丰富,兵字公司开始注重品牌建设和市场拓展。公司注册了“BingZi兵字”商标,并通过一系列的市场推广活动,提升了品牌的知名度和美誉度。同时,兵字公司还积极开拓国内外市场,与多家知名企业建立了长期稳定的合作关系,实现了业务的快速增长。

Fluke公司的发展小趣事

为了进一步提升公司的管理水平和市场竞争力,兵字公司决定进行企业规范化和市场化运作。公司建立了完善的管理体系和运营机制,优化了业务流程和组织结构,提高了工作效率和响应速度。同时,兵字公司还积极引进外部投资和战略合作伙伴,为公司的发展注入了新的活力和动力。

Component General Inc公司的发展小趣事

Component General Inc公司深知品质是企业的生命线。因此,公司建立了严格的质量管理体系,从原材料的采购到产品的生产、检测、包装等每一个环节都进行严格把控。这种对品质的执着追求,使得公司的产品赢得了客户的广泛信任和好评。

Feller US公司的发展小趣事

在电动汽车领域,技术创新是企业生存和发展的关键。菲斯克一直致力于研发更加先进、更加环保的电动汽车技术。经过多年的努力,公司终于在某项关键技术上取得了重大突破。这一突破不仅提升了电动汽车的性能和续航里程,还为公司赢得了市场的广泛认可。菲斯克凭借这一技术优势,成功推出了一系列备受好评的电动汽车产品,进一步巩固了其在市场中的地位。

问答坊 | AI 解惑

USB转串口

USB转串口的电路图…

查看全部问答>

DSP入门经验谈

入门并不难, 应该说,ti的28定点系列如2812,28016,以及piccolo系列硬件和固件编程都不是什么有多大难度。 例如2812,基本上搞清楚启动过程,搞清楚CMD文件,当然硬件设计的话还要关心上电顺序, 剩下的就和其他MCU没有什么不同。 当然,卖款 ...…

查看全部问答>

USB鼠标驱设备上传数据及过滤驱动问题

各位大大, 我想开发一款特殊鼠标,除了标准的鼠标数据外,还要另外携带一批数据上传,供PC端驱动处理,这些要上传的数据,是否可以直接放在标准鼠标数据后通过同一端点上传?这样在PC端没有装驱动的情况下,鼠标还能用吧? 或者,是不是可以这样 ...…

查看全部问答>

在直流电机调速中增量式PID控制算法的输出是怎么与PWM建立关系

各位大侠:我是菜鸟,最近我用单片机做一个PWM直流电机调速的实验,我用的是增量式PID控制算法,我有个问题不是很明白:那就是在这个系统中是怎样通过增量式PID控制算法的输出来控制PWM的,增量式PID控制算法的输出是怎么与PWM建立关系的,假设增量 ...…

查看全部问答>

LPC1768的一些资料。

这些资料是做智能家居系统收集的,有兴趣的可以看看。   1.周工SmartCortex M3-1700资料 https://bbs.eeworld.com.cn/thread-153450-1-1.html   2.几种LPC1700开发板原理图 https://bbs.eeworld.com.cn/thread-111150-1-1.html…

查看全部问答>

大家觉得英蓓特这个公司怎么样?

RT,要签约,不知道他们的福利待遇如何,而且武汉分公司和上海分公司哪个更好一些?   急呀,有了解的朋友请告知!~谢谢!~…

查看全部问答>

关于触摸屏的问题,请用过的同仁帮忙一下!谢谢

来看帖子的同仁先对您的热情帮助表示感谢,我的问题是这样的:我现在在用一个320*240的TFT液晶屏,并且附有触摸屏,现在屏已经能正常使用,触摸屏的驱动已经没有问题,已经可以准确读出触摸屏控制器输出的X,Y值,触摸屏控制芯片是ADS7843E, ...…

查看全部问答>

max232接两个串口互相干扰

用了max232的两路,接单片机和PC,但两个串口不能同时使用,否则两个串口都会乱码,但是单独接一个就能正常使用,232的接法都是很通用的接法,求解决办法?…

查看全部问答>

学单片机有前途还是嵌入式系统有前途

学单片机有前途还是嵌入式系统有前途我在深圳一直搞单片机的开发,接的项目各种各样,不计其数。很多朋友问我学习单片机有前途还是嵌入式系统有前途,毫无疑问的,当然是单片机有前途。嵌入式系统现在炒得很火,满街到处都是嵌入式系统的培训。遇到 ...…

查看全部问答>