标题:
单片机驱动带编码器直流电机 源程序
[打印本页]
作者:
SpringMean
时间:
2019-7-9 14:38
标题:
单片机驱动带编码器直流电机 源程序
#include<STC12C5A60S2.h>
//单片机头文件,储存一些殊寄存器的地址声明
#include<intrins.h>
//intrins头文件储存51编程中需要使用到空指令_nop_()、字符循环移位指令_crol_等
#include <stdio.h>
//stdio : "standard input & output"(标准输入输出),C/C++头文件,把多个编译单元(.c或者.cpp文件)公用的内容,单独放在一个文件里减少整体代码尺寸
#define usint unsigned short int //符号短整型
#define uchar unsigned char //无符号字符型
#define uint unsigned int //无符号整型
#define VALID 0 //0
#define INVALID 1 //1
#define LCD_data P0 //LCD数据端口P0
sbit LCD_RS = P2^7; //LCD命令和数据控制位,1:写数据位,0:写命令
sbit LCD_RW = P2^6; //LCD读写控制位
sbit LCD_EN = P2^5; //LCD使能位
sbit IN1 = P2^0; //电机
sbit IN2 = P2^1;
sbit ENA = P2^3;
uchar code title2[] = {"电机转速:"};
uchar code ascii[] =
{0x31,0x32,0x33,0x41,0x34,0x35,0x36,0x42,0x37,0x38,0x39,0x43,0x2A,0x30,0x23,0x44}; //数字和常用字符的ascii码
uint n = 0; //T0定时中断响应次数
uint n_pwm = 0; //用于调节pwm占空比
uint c = 0; //外部计数中断响应次数
uint flag_T0 = 0; //定时器T0溢出flag
uchar th = 0; //脉冲计数计算时的临时变量高位
uchar tl = 0; //……………………………………………低位
uint num_pulse; //脉冲个数
void delay_1ms(uint z){ //延时函数1ms
uint x,y;
for(x = z; x > 0; x--)
for(y = 920; y > 0; y--);
}
void write_cmd(uchar cmd){ //LCD写命令函数
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
P0 = cmd;
delay_1ms(6);
LCD_EN = 1;
delay_1ms(6);
LCD_EN = 0;
}
void write_dat(uchar dat){ //LCD写数据函数
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delay_1ms(5);
LCD_EN = 1;
delay_1ms(5);
LCD_EN = 0;
}
void lcd_pos(uchar X,uchar Y){ //X表示LCD的行数,Y表示LCD的列数
uchar pos;
if(X == 0){
X = 0x80;
}
else if(X == 1){
X = 0x90;
}
else if(X == 2){
X = 0x88;
}
else if (X == 3){
X = 0x98;
}
pos = X+Y ;
write_cmd(pos); //显示地址
}
void lcd_init(){
uchar i = 0;
write_cmd(0x30); //基本指令操作
delay_1ms(5);
write_cmd(0x0C); //显示开,关光标
delay_1ms(5);
write_cmd(0x01); //清除LCD的显示内容
delay_1ms(5);
lcd_pos(0,0); //将LCD光标定位到第一行第一列
}
void pulse_dispaly(uint fe) //显示脉冲个数
{
uchar i = 0;
uchar f[7];
for(i = 0; i < 7; i++)
f[i] = '0';
f[0] = ((fe)/100000) +0x30;//十万位的数字
f[1] = ((fe)%100000)/10000 +0x30;//万位的数字
f[2] = ((fe)%10000)/1000 +0x30;//千位的数字
f[3] = ((fe)%1000 )/100 +0x30;//百位的数字
f[4] = ((fe)%100 )/10 +0x30;//十位的数字
f[5] = ((fe)%10 ) +0x30;//个位的数字
f[6] = '\0';
i = 0;
lcd_pos(1,5); //将光标定位到第2行第6列开始显示
while(f[i] != '\0'){
write_dat(f[i]);
i++;
}
}
void display_text(int pos, uchar *text){ //显示一段字text、pos设置在第几行开头显示
uchar j;
lcd_pos(pos,0);
while(text[j]!='\0'){
write_dat(text[j]);
j++;
}
j=0;
}
void INIT(){ //初始化函数
TMOD = 0X51; //定时器初始化0101_0001
TH0 = (65536-922)/256; //定时器初值(1ms),0.001s/(1.085*10^(-6))s=922
TL0 = (65536-922)%256;
TH1 = 0X00; //计数器初值
TL1 = 0x00;
ET0 = 1; //允许中断T0
ET1 = 1;
EA = 1; //总中断开放
TR0 = 1; //启动T0
TR1 = 1; //启动T1
IN2 = 0; //电机初始化
IN1 = 1;
ENA = 0;
}
void main(){
uchar i;
INIT();
lcd_init(); //LCD初始函数
display_text(1, title2); //在第2行开头显示 "电机转速:"
while(1){
if (flag_T0 == 1){ //1s
/*脉冲计数(电机转速通过脉冲个数的方式输出)*/
th = TH1; //用临时变量读取计数器数值
tl = TL1;
num_pulse = th*256 + tl; //计数器16进制转10进制
TH1 = 0X00; //重新赋计数器的值
TL1 = 0x00;
pulse_dispaly(num_pulse); //循环调用显示函数
th = 0;
tl = 0;
/*脉冲计数*/
flag_T0 = 0;
}
}
}
void interrupt_Timer0() interrupt 1 { //定时器中断(1ms)
TR0 = 0;
TH0 = (65536-922)/256; //重新赋初值
TL0 = (65536-922)%256;
n++;
n_pwm++; //一个pwm脉冲周期为10ms,速度10档可调
ENA = 1;
if (n_pwm > 10) //超过一个pwm周期
n_pwm = 1;
if (n_pwm <= 5) //占空比50%
IN1 = 1; //pwm高电平
else
IN1 = 0; //pwm低电平
if(n == 1000){ //计满1s
flag_T0 = 1;
n = 0;
}
TR0 = 1;
}
void interrupt_Timer1() interrupt 3 { //计数器中断
TR1 = 0;
TH1 = 0x00; //重新赋值
TL1 = 0x00;
TR1 = 1;
}
复制代码
作者:
xuanmic
时间:
2020-1-16 21:50
感谢楼主的分享!!
作者:
1328091561
时间:
2020-5-13 22:13
终于找到了,谢谢楼主
作者:
西科大白鹅
时间:
2021-8-16 19:25
请问有这份代码的电路图吗?
作者:
西科大白鹅
时间:
2021-8-16 19:26
请问楼主可以分享一下这个程序的电路图吗?谢谢
作者:
bb1237
时间:
2023-5-23 16:48
请问楼主可以分享一下这个程序的电路图吗?谢谢
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1