近几天借了本《单片机C语言程序设计实训100例》在熟练单片机的C语言操作,进一步加深对单片机及C语言编程的了解。
然后我用keil和Proteus练习仿真,然后按照书本的练习仿真的时候发现 LCD1602只是亮而不会进行温度采集以及转速控制,我在网上查过相应的资料也咨询过同学,都不知道问题究竟出在哪里,能不能请问一下,是不是这个程序有问题?问题在哪个方面?怎样改比较全面?
#include
#include
#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_Title[] = "Here is Current";
uchar curr_temp_buf[] = "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);//写入温度符号
}
}
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缓冲
curr_temp_buf[11] = Display_Digit[0] + '0';
curr_temp_buf[10] = '.';
curr_temp_buf[9] = Display_Digit[1] + '0';
curr_temp_buf[8] = Display_Digit[2] + '0';
curr_temp_buf[7] = Display_Digit[3] + '0';
//高位为0不显示
if(Display_Digit[3] == 0) curr_temp_buf[7] = ' ';
//高位为0且次高位为0不显示
if(Display_Digit[2] == 0 && Display_Digit[3] == 0)
{
curr_temp_buf[8] = ' ';
}
if(flag)
{
if(curr_temp_buf[8] == ' ')
{
curr_temp_buf[8] == '-';
}else if(curr_temp_buf[7] == ' ')
{
curr_temp_buf[7] == '-';
}else
{
curr_temp_buf[6] == '-';
}
}
//在第一行显示标题
set_LCD_Pos(0x00);
for(i = 0; i < 16; i++)
{
write_LCD_Data(temp_Title);
}
//在第二行显示实际温度
set_LCD_Pos(0x40);
for(i = 0; i < 16; i++)
{
write_LCD_Data(curr_temp_buf);
}
//显示温度符号℃
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);
}