关于【温度控制直流电机转速】程序代码的问题

AngeloChou 发布于 2013/05/16 19:25
阅读 1K+
收藏 1

近几天借了本《单片机C语言程序设计实训100例》在熟练单片机的C语言操作,进一步加深对单片机及C语言编程的了解。
然后我用keil和Proteus练习仿真,然后按照书本的练习仿真的时候发现 LCD1602只是亮而不会进行温度采集以及转速控制,我在网上查过相应的资料也咨询过同学,都不知道问题究竟出在哪里,能不能请问一下,是不是这个程序有问题?问题在哪个方面?怎样改比较全面?

#include <reg51.h>
#include <intrins.h>


#define uchar unsigned char
#define uint unsigned int 
#define DelayNop() {_nop_(); _nop_(); _nop_(); _nop_();}
#define TEMP_1  10
#define TEMP_2  15
#define TEMP_3  25
#define TEMP_4  30


sbit DQ = P3^3;
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit MA = P1^0;     
sbit MB = P1^1;   
sbit PWM1 = P1^2;


uchar code temp_DISP_Title[] = "Here is Current";
uchar current_temp_Display_Buffer[] = "temp:           ";


uchar code temperature_char[8] = 
{0x0C, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00};
uchar code df_Table[] = 
{0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 9};
uchar CurrentT = 0;
uchar Signed_temp = 0;
uchar Temp_Value[] = {0x00, 0x00};
uchar Back_temp_Value[] = {0xFF, 0xFF};
uchar Display_Digit[] = {0, 0, 0, 0};
bit DS18B20_IS_OK = 1;
uint tCount = 0;


void delayXus(int x)//延迟程序1(ms)
{
uchar i;
while(x--)
{
for(i = 0; i < 120; i++);
}
}


bit LCD_Busy_Check()//LCD忙检查
{
bit Result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
DelayNop();
Result = (bit) (P0 & 0x80);
LCD_EN = 0;
return Result;
}


void write_LCD_Cmd(uchar cmd)//向LCD写指令
{
while(LCD_Busy_Check());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();_nop_();
P0 = cmd;
DelayNop();
LCD_EN = 1;
DelayNop();
LCD_EN = 0;
}


void write_LCD_Data(uchar dat)//向LCD写数据
{
while(LCD_Busy_Check());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
DelayNop();
LCD_EN = 1;
DealyNop();
LCD_EN = 0;
}


void LCD_init() //LCD初始化
{
delayXus(2);
write_LCD_Cmd(0x01);//
delayXus(2);
write_LCD_Cmd(0x38);//显示开,光标关
delayXus(2);
write_LCD_Cmd(0x0c);//字符进入模式:屏幕不动,字符后移
delayXus(2);
write_LCD_Cmd(0x06);//清屏
delayXus(2);
}


void set_LCD_Pos(uchar pos)//设置显示位置
{
write_LCD_Cmd(pos | 0x80);
}




void write_New_LCD_char()
{
uchar i;
write_LCD_Cmd(0x40);
for(i = 0; i < 8; i++)
{
write_LCD_Data(temperature_char[i]);//写入温度符号
}
}


void delay_(uint x)//延迟程序2
{
while(--x);
}


uchar read_byte()//读一字节
{
uchar i, dat = 0;
DQ = 1;_nop_();
for(i = 0; i < 8; i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
_nop_();_nop_();
if(DQ)
dat |= 0x80;
delay_(30);
DQ = 1; 
}


return dat;
}


uchar write_byte(uchar dat)//写一字节
{
uchar i;
for(i = 0; i < 8; i++)
{
DQ = 0;
DQ = dat & 0x01;
delay_(5);
DQ = 1;
dat >>= 1;
}
}
   
uchar DS18B20_init() //DS18B20初始化
{
  uchar status;
DQ = 1; delay_(8);
DQ = 0; delay_(90);
DQ = 1; delay_(8);
status = DQ; 
delay_(100);
DQ = 1;

return status;//初始化成功返回0 
}


void read_temp()//读温度值
{
if(DS18B20_init() == 1)   //DS18B20出故障
{
DS18B20_IS_OK = 0;
}else
{
write_byte(0xCC);
write_byte(0x44);
DS18B20_init();
write_byte(0xCC);
write_byte(0xBE);
Temp_Value[0] = write_byte(0);// 温度低8位
Temp_Value[1] = write_byte(0);// 温度高8位
DS18B20_IS_OK = 1;
}
}


void display_temp()
{
uchar i;
uchar t = 150;//延时值
uchar flag = 0;//负数标识  
//如果为负数取反加1,并设置负数标识
if((Temp_Value[1] & 0xF8) == 0xF8)
{
Temp_Value[1] = ~Temp_Value[1];
Temp_Value[0] = ~Temp_Value[0] + 1;
if(Temp_Value[0] == 0x00)
Temp_Value[1]++;
flag = 1;
}
Display_Digit[0] = df_Table[Temp_Value[0] & 0x0F];
CurrentT = ((Temp_Value[0] & 0xF0) >> 4) | ((Temp_Value[1] & 0x07) << 4);
Signed_temp = !flag ? CurrentT : - CurrentT;
Display_Digit[3] = CurrentT / 100;
Display_Digit[2] = CurrentT % 100 /10;
Display_Digit[1] = CurrentT % 10;
//刷新LCD缓冲
current_temp_Display_Buffer[11] = Display_Digit[0] + '0';
current_temp_Display_Buffer[10] = '.';
current_temp_Display_Buffer[9] = Display_Digit[1] + '0';
current_temp_Display_Buffer[8] = Display_Digit[2] + '0';
current_temp_Display_Buffer[7] = Display_Digit[3] + '0';
//高位为0不显示
if(Display_Digit[3] == 0) current_temp_Display_Buffer[7] = ' ';
//高位为0且次高位为0不显示
if(Display_Digit[2] == 0 && Display_Digit[3] == 0) 
{
current_temp_Display_Buffer[8] = ' ';
}
if(flag)
{
if(current_temp_Display_Buffer[8] == ' ')
{
current_temp_Display_Buffer[8] == '-';
}else if(current_temp_Display_Buffer[7] == ' ')
{
current_temp_Display_Buffer[7] == '-';
}else
{
current_temp_Display_Buffer[6] == '-';
}
}
//在第一行显示标题
set_LCD_Pos(0x00);
for(i = 0; i < 16; i++)
{
write_LCD_Data(temp_DISP_Title[i]);
}
//在第二行显示实际温度
set_LCD_Pos(0x40);
for(i = 0; i < 16; i++)
{
write_LCD_Data(current_temp_Display_Buffer[i]);
}
//显示温度符号℃
set_LCD_Pos(0x4D);
write_LCD_Data(0x00);
set_LCD_Pos(0x4E);
write_LCD_Data('C');   
}


void T0_int()interrupt 1
{
TH0 = -50000 / 256;
TL0 = -50000 % 256;
read_temp();//读取温度
if(!DS18B20_IS_OK) return; //读错时退出
//读取正常且温度发生变化则刷新显示
if(Temp_Value[0] != Back_temp_Value[0] || Temp_Value[1] != Back_temp_Value[1])
{
Back_temp_Value[0] = Temp_Value[0];
Back_temp_Value[1] = Temp_Value[1];
display_temp();
}
//>=TEMP_4℃ 或 <=TEMP_1℃ ,电动全速转动,占空比为100%
if(Signed_temp >= TEMP_4)  Signed_temp = TEMP_4;
if(Signed_temp <= TEMP_1)  Signed_temp = TEMP_1;
//>= TEMP_3 加速正转  TEMP_4全速正转
if(Signed_temp >= TEMP_3)
{
MA = 1; MB = 0; //正转
if(Signed_temp == TEMP_3) //占空比:0%
{
PWM1 = 0;
delayXus(30);
return;
}else 
if(Signed_temp == TEMP_4) //占空比:100%
{
PWM1 = 1;
delayXus(30);
return;
}
PWM1 = 1; //占空比:0~100%
delayXus(Signed_temp - TEMP_3);
PWM1 = 0;
delayXus(TEMP_4 - Signed_temp);


}else
if(Signed_temp <= TEMP_2)//<= TEMP_2 加速反转 TEMP_1 全速反转
{
MA = 0; MB = 1;   //反转
if(Signed_temp == TEMP_2) //占空比:0%
{
PWM1 = 0;
delayXus(10);
return;
}else 
if(Signed_temp == TEMP_1) //占空比:100%
{
PWM1 = 1;
delayXus(10);
return;
}
PWM1 = 1; //占空比:0~100%
delayXus(TEMP_2 - Signed_temp);
PWM1 = 0;
delayXus(Signed_temp - TEMP_1);
}else//由运动→停止
{
MA = 0;
MB = 0;
}
}


void main()
{
LCD_init();
read_temp();
delay_(50000);
delay_(50000);
TMOD = 0x01;
TH0 = -50000 / 256;
TL0 = -50000 % 256;
IE = 0x82;
TR0 = 1;
while(1);
}

加载中
0
地瓜儿
地瓜儿
首先保证硬件焊接是没有问题的,在调试程序、、、
AngeloChou
AngeloChou
回复 @地瓜头 : 没 我现在想问的是程序问题 不是硬件方面的 就想知道程序它哪里出了错
地瓜儿
地瓜儿
回复 @AngeloChou : 单片机可以反复烧写使用 就你那几次 不要担心单片机会挂掉,有实物操作,仿真永远不是真实的,哪怕仿真通过 在实际的时候也不一定行
AngeloChou
AngeloChou
回复 @地瓜头 : 不是 现在还停留在仿真阶段 我仿真就是为了检查程序的正确性的 就是因为仿真没有结果 我才懵了 还没有到实物程序的烧录阶段呢 还是在检查各个模块的程序阶段而已
地瓜儿
地瓜儿
回复 @AngeloChou : 一般学校或者公司都有这样的开发板,首先运行没有问题的,排除不是因为硬件的问题,在调试你的程序,硬件无问题,单片机与lcd之间的低平与高平不对、、、这个需要差看相关的lcd说明书
AngeloChou
AngeloChou
不是 目前我还在仿真这一阶段就卡壳了...
0
Jordan
Jordan

1602只是用来显示的

怎么能用来控制

AngeloChou
AngeloChou
1602是用来显示采集的温度的 控制是用采集到的温度来控制的 说简单一点就是温控
0
w
wilinyu
我也在弄这个,可是一直没有进展,你现在弄好了吗?
AngeloChou
AngeloChou
没 程序方面已经有问题 你要是弄好了分享一下经验吧
返回顶部
顶部