求助,怎么用51单片机产生PWM波控制直流电机随温度变化而改变?
时间:10-02
整理:3721RD
点击:
我在做用单片机温控直流电机转速的,想法是随着温度越高速度越快,连接一块lcd1602液晶屏,想用pwm波实现,可是总是出错,求大神帮忙看一下,程序到底怎么编,我的程序是这样的
#include<reg51.h>
#include<intrins.h>
#include"lcd.h"
#include"temp.h"
#include<math.h>
uint t;
float b;
sbit moto=P1^0;
uchar CNCHAR[6] = "摄氏度";
uchar m1;
void LcdDisplay(int);
void UsartConfiguration();
void sudu(char speed)
{
if(speed>=-100&&speed<=100)
{
m1=abs(speed);
moto=1;
}
}
void delay(uint i)
{
while(i--);
}
/*******************************************************************************
* 函数名 : main
* 函数功能 : 主函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void main()
{ char i;
UsartConfiguration();
LcdInit(); //初始化LCD1602
LcdWriteCom(0x88); //写地址 80表示初始地址
LcdWriteData('C');
moto=0;
TMOD=0x02; /* 设定T0的工作模式为2 */
TH0=0x9B; /* 装入定时器的初值*/ TL0=0x9B;
EA=1; /* 开中断*/
ET0=1; /* 定时器0允许中断*/
TR0=1; /* 启动定时器0 */
while(1)
{
LcdDisplay(Ds18b20ReadTemp());
// Delay1ms(1000);//1s钟刷一次
t=Ds18b20ReadTemp();
b=t;
t=b*0.0625;
if(t>=25)
for(i=0;i<=100;i++)
{
sudu(i);
delay(5000);
}
}
}
/*******************************************************************************
* 函数名 : LcdDisplay()
* 函数功能 : LCD显示读取到的温度
* 输入 : v
* 输出 : 无
*******************************************************************************/
void LcdDisplay(int temp) //lcd显示
{
unsigned char i, datas[] = {0, 0, 0, 0, 0}; //定义数组
float tp;
if(temp< 0) //当温度值为负数
{
LcdWriteCom(0x80); //写地址 80表示初始地址
SBUF='-';//将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
LcdWriteData('-'); //显示负
//因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算由?.5,还是在小数点后面。
}
else
{
LcdWriteCom(0x80); //写地址 80表示初始地址
LcdWriteData('+'); //显示正
SBUF='+';//将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
//如果温度是正的那么,那么正数的原码就是补码它本身
temp=tp*0.0625*100;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
datas[0] = temp / 10000;
datas[1] = temp % 10000 / 1000;
datas[2] = temp % 1000 / 100;
datas[3] = temp % 100 / 10;
datas[4] = temp % 10;
LcdWriteCom(0x82); //写地址 80表示初始地址
LcdWriteData('0'+datas[0]); //百位
SBUF = '0'+datas[0];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x83); //写地址 80表示初始地址
LcdWriteData('0'+datas[1]); //十位
SBUF = '0'+datas[1];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x84); //写地址 80表示初始地址
LcdWriteData('0'+datas[2]); //个位
SBUF = '0'+datas[2];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x85); //写地址 80表示初始地址
LcdWriteData('.'); //显示 ‘.’
SBUF = '.';//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x86); //写地址 80表示初始地址
LcdWriteData('0'+datas[3]); //显示小数点
SBUF = '0'+datas[3];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x87); //写地址 80表示初始地址
LcdWriteData('0'+datas[4]); //显示小数点
SBUF = '0'+datas[4];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
for(i=0; i<6; i++)
{
SBUF = CNCHAR[i];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
}
}
/*******************************************************************************
* 函 数 名 :UsartConfiguration()
* 函数功能 :设置串口
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void UsartConfiguration()
{
SCON=0X50; //设置为工作方式1
TMOD=0X20; //设置计数器工作方式2
PCON=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,注意波特率是4800的
TL1=0XF3;
// ES=1; //打开接收中断
// EA=1; //打开总中断
TR1=1; //打开计数器
}
#include<reg51.h>
#include<intrins.h>
#include"lcd.h"
#include"temp.h"
#include<math.h>
uint t;
float b;
sbit moto=P1^0;
uchar CNCHAR[6] = "摄氏度";
uchar m1;
void LcdDisplay(int);
void UsartConfiguration();
void sudu(char speed)
{
if(speed>=-100&&speed<=100)
{
m1=abs(speed);
moto=1;
}
}
void delay(uint i)
{
while(i--);
}
/*******************************************************************************
* 函数名 : main
* 函数功能 : 主函数
* 输入 : 无
* 输出 : 无
*******************************************************************************/
void main()
{ char i;
UsartConfiguration();
LcdInit(); //初始化LCD1602
LcdWriteCom(0x88); //写地址 80表示初始地址
LcdWriteData('C');
moto=0;
TMOD=0x02; /* 设定T0的工作模式为2 */
TH0=0x9B; /* 装入定时器的初值*/ TL0=0x9B;
EA=1; /* 开中断*/
ET0=1; /* 定时器0允许中断*/
TR0=1; /* 启动定时器0 */
while(1)
{
LcdDisplay(Ds18b20ReadTemp());
// Delay1ms(1000);//1s钟刷一次
t=Ds18b20ReadTemp();
b=t;
t=b*0.0625;
if(t>=25)
for(i=0;i<=100;i++)
{
sudu(i);
delay(5000);
}
}
}
/*******************************************************************************
* 函数名 : LcdDisplay()
* 函数功能 : LCD显示读取到的温度
* 输入 : v
* 输出 : 无
*******************************************************************************/
void LcdDisplay(int temp) //lcd显示
{
unsigned char i, datas[] = {0, 0, 0, 0, 0}; //定义数组
float tp;
if(temp< 0) //当温度值为负数
{
LcdWriteCom(0x80); //写地址 80表示初始地址
SBUF='-';//将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
LcdWriteData('-'); //显示负
//因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算由?.5,还是在小数点后面。
}
else
{
LcdWriteCom(0x80); //写地址 80表示初始地址
LcdWriteData('+'); //显示正
SBUF='+';//将接收到的数据放入到发送寄存器
while(!TI); //等待发送数据完成
TI=0; //清除发送完成标志位
tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
//如果温度是正的那么,那么正数的原码就是补码它本身
temp=tp*0.0625*100;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
datas[0] = temp / 10000;
datas[1] = temp % 10000 / 1000;
datas[2] = temp % 1000 / 100;
datas[3] = temp % 100 / 10;
datas[4] = temp % 10;
LcdWriteCom(0x82); //写地址 80表示初始地址
LcdWriteData('0'+datas[0]); //百位
SBUF = '0'+datas[0];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x83); //写地址 80表示初始地址
LcdWriteData('0'+datas[1]); //十位
SBUF = '0'+datas[1];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x84); //写地址 80表示初始地址
LcdWriteData('0'+datas[2]); //个位
SBUF = '0'+datas[2];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x85); //写地址 80表示初始地址
LcdWriteData('.'); //显示 ‘.’
SBUF = '.';//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x86); //写地址 80表示初始地址
LcdWriteData('0'+datas[3]); //显示小数点
SBUF = '0'+datas[3];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
LcdWriteCom(0x87); //写地址 80表示初始地址
LcdWriteData('0'+datas[4]); //显示小数点
SBUF = '0'+datas[4];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
for(i=0; i<6; i++)
{
SBUF = CNCHAR[i];//将接收到的数据放入到发送寄存器
while (!TI); //等待发送数据完成
TI = 0;
}
}
/*******************************************************************************
* 函 数 名 :UsartConfiguration()
* 函数功能 :设置串口
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void UsartConfiguration()
{
SCON=0X50; //设置为工作方式1
TMOD=0X20; //设置计数器工作方式2
PCON=0X80; //波特率加倍
TH1=0XF3; //计数器初始值设置,注意波特率是4800的
TL1=0XF3;
// ES=1; //打开接收中断
// EA=1; //打开总中断
TR1=1; //打开计数器
}
没详细去测试过, 你也没说清楚是什么错误, 看上去有两个可能的错误点, 看能否帮到你吧:
1. 启动了 Timer0 的计时器中断, 却没有处理中断程序
2. 在 sudo 子程序有 moto=1, 却没有任何程序把它关掉, moto 只会等于 1