C51单片机产生PWM输入L298驱动电机,控制启停,正反转,加减速,这些都可以实现,可以以反馈到LCD1062上。但是通过T1定时器、外中断INT1组合测速(脉冲频率)无法实时显示到屏幕,就是可以显示,但是数值不变化。也不知道为啥。
个人认为问题应该出在测速模块或者外中断1函数里,但是找不出原因,请大佬看看!
单片机源程序如下:
- #include <reg52.h>
- #include<string.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
-
- sbit lcdrs=P2^0; //寄存器选择,0:数据寄存器。1:为状态/命令寄存器
- sbit lcden=P2^1; //--LCD控制引脚
- sbit speed=P3^2; //测速端口
- sbit ENA=P2^2; //电机使能控制端
- sbit key1=P1^0; //启动按键
- sbit key2=P1^1; //正转按键
- sbit key3=P1^2; //反转按键
- sbit key4=P1^3; //加速按键
- sbit key5=P1^4; //减速按键
- sbit key6=P1^5; //停止按键
- sbit Zheng=P1^6; //正转输出端口
- sbit Fan=P1^7; //反转输出端口
- uchar Timer0_flag=4;
- uchar Timer0_BiaoZhi=0;//初始化占空比为1:3(高:低)
- uchar gewei;
- uchar shiwei;
- uchar baiwei;
- /******标志位设置*****/
- uchar KEY1=0;//优先级标志
- uchar KEY2=0;//加速标志
- uchar INT1_FLAG=0;
- uchar COUNTER_high=0;
- uchar COUNTER_low=0;
- uchar SUM=0;
- uint TIMER1_COUNTER=0;
- uint INT1_tingzhi=0; //在要测速时置0
- /****面板显示****/
- uchar code lcd_desktop10[]="WUU";//不显示
- uchar code lcd_desktop11[]="RUN";//运行
- uchar code lcd_desktop12[]="FWD";//正转
- uchar code lcd_desktop13[]="REV";//反转
- uchar code lcd_desktop14[]="JIA";//加速
- uchar code lcd_desktop15[]="JAN";//减速
- uchar code lcd_desktop16[]="OFF";//停止
- uchar code num[]={'0','1','2','3','4','5','6','7','8','9'};//要显示的转速数字。
- //-----lcd液晶屏头文件-----//
- /**延时函数**/
- void delayms(uchar xms)
- {
- uchar i,j;
- for(i=xms;i>0;i--)
- for(j=110;j>0;j--);
- }
- /****LCD写命令******/
- void write_command(uchar com)//com写入命令
- {
- lcdrs=0; //LED选择输入命令
- P0=com; //向P0口输入命令39-32端口
- delayms(2); //延时
- lcden=1; //打开LCD使能
- delayms(2); //一个高脉冲
- lcden=0; //关闭LED使能
- }
- /**************LCD写数据,来源网上*********/
- void write_data(uchar date)//数据为DATA
- {
- lcdrs=1; //设置为输入数据
- P0=date; //将数据赋给P0口
- delayms(2); //延时
- lcden=1; //置高
- delayms(2);
- lcden=0; //置低完成高脉冲
- }
- /********LCD初始化,来源网上****************/
- void lcd_init()//显示模式设置
- {
- lcden=0;
- write_command(0x38); //设置16×2 显示5×7点阵,8位数据接口
- write_command(0x0c); //设置开始显示不显示光标(指令4)
- write_command(0x06); //写一个字符后地址指针加一(指令3)
- write_command(0x01); //显示清零数据指针清零(指令1)
- }
- /**电机初始化函数**/
- void motor_init(void)
- {
- ENA=0; // 停止
- }
- void ZhongDuanKaiQi(void)
- {
- EA=1;
- ET0=1; //计时器0允许中断。产生脉冲。
- ET1=1; //计时器1允许中断。对低电平进行计时。
- //EX1=1; //INT0允许中断。测速。由外部来启动。
- IT1=1; //外部中断1低电平触发。
- PX1=0; //外中断0为低级中断。
- PT0=1; //定时器0为高优先级中断
- PT1=0; //外中断1为低优先级中断
- TMOD=0x12;//定时器工作方式控制
- }
- /***定时器T1初始化!!!等待外部脉冲的到来***/
- void Timer1_init(void)
- {
- TH1=0;
- TL1=0; //等待外部脉的到来。INT1
- }
- /*****定时T0初始化*****/
- void Timer0_init(void)
- {
- TH0=0;
- TL0=0;
- TR0=1;
- }
- /********测速模块,显示速度*******/
- void speed_test(void)
- {
- // TIMER1_COUNTER;
- COUNTER_high=TH1;
- COUNTER_low=TL1;
- SUM=COUNTER_high*256+COUNTER_low+TIMER1_COUNTER*65536;//得到的是多少us。
- //count:每百16位进1,16位为65536;TH1:每8位进1,8位为256;TL1:每次进1;即TL1由0增加度到内255时,TH1加1,TL1回0,TH1由0增加到65535时,count加1,TH1回0,三者之和为总次数。
- SUM=SUM/1000; //化为毫秒。
- SUM=1000/SUM; //圈每秒。
- SUM=SUM*60; //圈每分钟;三位数。
- gewei=SUM%10+0x30;
- shiwei=SUM/10%10+0x30;
- baiwei=SUM/100+0x30;
- write_command(0x80+0x4c);
- write_data(baiwei);
- write_command(0x80+0x4d);
- write_data(shiwei);
- write_command(0x80+0x4e);
- write_data(gewei);
- SUM=0;
- TIMER1_COUNTER=0;
- }
- /********外中断1函数**********/
- void INT1_QIDONG() interrupt 2
- {
- INT1_tingzhi++;
- if(INT1_tingzhi==5)
- {
- INT1_tingzhi=5;EX1=0;//关闭中断。
- }
- if(INT1_tingzhi<=4)
- {
- INT1_FLAG++;
- if(INT1_FLAG==2)
- {
- INT1_FLAG=0;TR1=0;speed_test();
- }
- else
- {
- Timer1_init();
- TR1=1;
- }
- }
- }
- /******定时器T1计数*******/
- void Timer1_QIDONG() interrupt 3
- {
- TIMER1_COUNTER++;
- }
- /****T0中断发出信号并进行通道选择****/
- void Timer0() interrupt 1
- {
- Timer0_flag--;
- if((Timer0_BiaoZhi)>=(Timer0_flag))
- {
- if(KEY2==0)
- {
- Zheng=1;Fan=0;
- }
- else
- {
- Zheng=0;Fan=1;
- }
- }
- else
- {
- Zheng=0;Fan=0;
- }
- if(Timer0_flag==0) Timer0_flag=5;
- }
- void Guan(void)
- {
- ET0=0;
- EX1=0;
- ET1=0;
- }
- void keyscan() //按键扫描函数
- {
- uint i=0;
- if(key1==0) //按键K1启动按钮。只有该位启动时,后面的几位才有效。启动T0计数开始发出脉冲。
- {
- delayms(10);
- if(key1==0)
- {
- while(!key1);
- KEY1=5;
- Fan=0;
- Zheng=0;
- ENA=1;
- KEY2=0;//初始化为正转。
- Timer0_BiaoZhi=0;
- Timer0_flag=4;
-
- ZhongDuanKaiQi();//开启中断
- Timer0_init();// 初始化并开始发出脉冲外中断已经开启。
- EX1=1; //外中断开启;测速,显示速度。
-
- write_command(0x80);
- for(i=0;i<strlen(lcd_desktop10);i++)//显示正转。
- write_data(lcd_desktop11[i]);
- }
- }
-
- if(key2==0&&KEY1==5) //按键K2按下,(正转)只改变转向(标志位改变输出端口)
- {
- delayms(10);
- if(key2==0)
- {
- while(!key2);
- KEY2=0; //正转标志,电机正向旋转。
- //KEY2=(~1);
-
- KEY1=5;
- write_command(0x80);
- for(i=0;i<strlen(lcd_desktop11);i++)//显示正转。
- write_data(lcd_desktop12[i]);
- }
- }
-
- if(key3==0&&KEY1==5) //按键K3按下,(反转)只改变转向
- {
- delayms(10);
- if(key3==0)
- {
- while(!key3);
- KEY2=~0; //反转标志。
- //KEY2=(~0);
-
- KEY1=5;
- write_command(0x80);
- for(i=0;i<strlen(lcd_desktop12);i++)//显示反转。
- write_data(lcd_desktop13[i]);
- }
- }
- if(key4==0&&KEY1==5) //按键K4按下,(加速)改变装入的数值?循环次数?执行if里面的语句,通过size++来改变幅值的频率
- {
- delayms(10);
- if(key4==0)
- {
- while(!key4);
- if(Timer0_BiaoZhi<4)
- {
- Timer0_BiaoZhi++;
- }
- else
- {
- Timer0_BiaoZhi=4;
- }
- EX1=1;
- KEY1=5;
- write_command(0x80);
- for(i=0;i<strlen(lcd_desktop13);i++)//显示加速。
- write_data(lcd_desktop14[i]);
- }
-
- }
-
- if((key5==0)&&(KEY1==5)) //按键K5按下,(减速)对其它标志位没有影响。
- {
- delayms(5);
- if(key5==0)
- {
- while(!key5);
- if(Timer0_BiaoZhi==0)
- {
- Timer0_BiaoZhi=0;
- }
- else
- {
- Timer0_BiaoZhi--;
- }
- EX1=1;
- KEY1=5;
- write_command(0x80);
- for(i=0;i<strlen(lcd_desktop14);i++)//显示减速。
- write_data(lcd_desktop15[i]);
- }
- }
- if((key6==0)&&(KEY1==5))//按键K6按下,电机停止转动使能端和计数启动关闭,计数器工作否?设立标志位。此按键按下后除K1外无法启动
- {
- delayms(5);
- if(key6==0)
- {
- while(!key6);
- //置位,保证后续操作正常。
-
-
-
- EA=0; //总中断关
- motor_init(); //电机关
- Guan();
- write_command(0x80);
- for(i=0;i<strlen(lcd_desktop15);i++)//显示停止。
- write_data(lcd_desktop16[i]);
- }
- }
- }
-
- /*主函数*/
- void main()
- {
- ZhongDuanKaiQi();//初始化
- motor_init(); //电机停止
- lcd_init();
- while(1)
- {
- keyscan();
-
- }
- }
复制代码
电路图和程序,可以仿真。
电机控制及显示.zip
(68.96 KB, 下载次数: 8)
|