有关题目
实现代码
注意:①注意修改驱动代码时要留意一下onewire.c中单总线延时函数,是
STC89C52RC
,还是15系列
的,15系列的单片机速度比51快8~12倍,需要修改对应的延时函数
。②实现pwm控制电机实现不同的转动速度,通过调占空比
实现的。需要结合点击转动的频率。③剩余时间为零时,需要停止pwm信号的输出。
onewire.c中具体修改如下
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
while(t--)
{
signed char i = 0;
for (i = 0; i < 12; i++);
}
}
实现风格①main.c
#include "STC15F2K60S2.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
uchar temp;//实时温度
uchar time;//倒计时时间
uchar mod = 1;//模式
code uchar tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf, 0xc6};
//-, C 11 12
uchar pwm_val, pwm_cnt = 0;
bit flag_s7 = 0;//初始化0为显示剩余工作时间
void sys_init();//系统初始化
uchar rd_temp();
void key_handle();
void led();
//显示模块
void dsp_smg_bit(uchar pos, val);//位显示数码管
void display();
void dsp_time();
void dsp_temp();
void delay_k(uchar t);
void Delay1ms(); //@12.000MHz
void main()
{
sys_init();
while(1)
{
temp = rd_temp();//实时读取温度
key_handle();//按键处理
display();//界面显示
if (!time)
{
ET1 = 0;
P34 = 0;
}
else
{
ET1 = 1;
}
led();//led显示
}
}
void led()
{
if (time > 0)
{
if (mod == 1)
{
P2 = (P2 & 0x1f) | 0x80;
L1 = 0;
}
else if (mod == 2)
{
P2 = (P2 & 0x1f) | 0x80;
L2 = 0;
}
else if (mod == 3)
{
P2 = (P2 & 0x1f) | 0x80;
L3 = 0;
}
}
else
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
}
}
void display()
{
if (!flag_s7)
{
dsp_time();
}
else
{
dsp_temp();
}
}
void dsp_time()
{
dsp_smg_bit(1, 11);
dsp_smg_bit(2, mod);
dsp_smg_bit(3, 11);
dsp_smg_bit(4, 10);
dsp_smg_bit(5, 0);
dsp_smg_bit(6, time / 100);
dsp_smg_bit(7, time / 10 % 10);
dsp_smg_bit(8, time % 10);
}
void dsp_temp()
{
dsp_smg_bit(1, 11);
dsp_smg_bit(2, 4);
dsp_smg_bit(3, 11);
dsp_smg_bit(4, 10);
dsp_smg_bit(5, 10);
dsp_smg_bit(6, temp / 10);
dsp_smg_bit(7, temp % 10);
dsp_smg_bit(8, 12);
}
void key_handle()
{
if (!S4)
{
delay_k(20);
if (!S4)
{
while(!S4)
{
display();
}
mod++;
if (mod >= 4)
mod = 1;
//不同模式,对应转机速度不同
if (mod == 1)
pwm_val = 2;
else if (mod == 2)
pwm_val = 3;
else if (mod == 3)
pwm_val = 7;
}
}
if (!S5)
{
delay_k(20);
if (!S5)
{
while(!S5)
{
display();
}
time += 60;
if (time >= 180)
time = 0;
}
}
if (!S6)
{
delay_k(20);
if (!S6)
{
while(!S6)
{
display();
}
time = 0;
}
}
if (!S7)
{
delay_k(20);
if (!S7)
{
while(!S7)
{
display();
}
flag_s7 = !flag_s7;
}
}
}
void dsp_smg_bit(uchar pos, val)
{
P2 = (P2 & 0x1f) | 0xc0;
P0 = 1 << (pos - 1);
P2 = (P2 & 0x1f) | 0xe0;
P0 = tab[val];
Delay1ms();
P0 = 0xff;
P2 &= 0x1f;
}
uchar rd_temp()
{
uchar t = 0, l, h;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
l = Read_DS18B20();
h = Read_DS18B20();
t = (h << 4);
t |= (l >> 4);
return t;
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delay_k(uchar t)//大约延时t * 10 us,用于消抖
{
while(t--)
display();
}
//100us * 10
void timer1() interrupt 3
{
if (++pwm_cnt <= pwm_val)
{
P34 = 1;
}
else
{
P34 = 0;
if (pwm_cnt == 10)
pwm_cnt = 0;
}
}
void timer0() interrupt 1
{
static uint i1 = 0;
if (++i1 == 500)
{
i1 = 0;
if (time > 0)
--time;
}
}
void sys_init()
{
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0xaf;
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 &= 0x1f;
AUXR &= 0x7F; //定时器时钟12T模式
TMOD = 0x00; //设置定时器模式
//2ms
TL0 = 0x30; //设置定时初值
TH0 = 0xF8; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
//100us
TL1 = 0x9C; //设置定时初值
TH1 = 0xFF; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET0 = 1;
ET1 = 0;//由time 决定是否打开
EA = 1;
}
实现风格②main.c
#include "STC15F2K60S2.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
//PWM
unsigned char pwm_value = 2;
unsigned char pwm_count = 0;
uchar key_val = 20;
uchar wind = 1;
uchar time = 0;
uchar flag = 0;
uchar flag_temp = 0;
uchar temp = 0;
unsigned char dspcom = 0;//位选线
unsigned char dspbuf[8] = {11,10,11,10,10,10,10,10};//显示缓冲区
code unsigned char tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0xc6};
//11 - 12 C
void sys_init(void);
void key_scanf(void);
void key_proc();
void display();
uchar read_temputerature();
void led_control();
void main()
{
sys_init();
while(1)
{
key_proc();
if (flag_temp)
{
flag_temp = 0;
temp = read_temputerature();
}
//实时显示
if (flag == 1)
{
dspbuf[1] = 4;
dspbuf[4] = 10;
dspbuf[5] = temp / 10;
dspbuf[6] = temp % 10;
dspbuf[7] = 12;
}
else
{
dspbuf[1] = wind;
dspbuf[4] = 0;
dspbuf[5] = time / 100;
dspbuf[6] = time / 10 % 10;
dspbuf[7] = time % 10;
}
led_control();
if (!time)
{
ET1 = 0;
P34 = 0;
}
else
{
ET1 = 1;
}
if (wind == 1) pwm_value = 2;
else if (wind == 2) pwm_value = 3;
else if (wind == 3) pwm_value = 7;
}
}
void led_control()
{
if (time != 0)
{
if (wind == 1)
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xfe;
P2 &= 0x1f;
}
else if (wind == 2)
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xfd;
P2 &= 0x1f;
}
else if (wind == 3)
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xfb;
P2 &= 0x1f;
}
}
else
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 &= 0x1f;
}
}
uchar read_temputerature()
{
uchar l, h, t = 0;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
//这边看情况延时
//while (!DQ); //Delay200us();
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xbe);
l = Read_DS18B20();
h = Read_DS18B20();
t |= h;
t <<= 4;
t |= (l >> 4);
return t;
}
void sys_init()
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 &= 0x1f;
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0xaf;
P2 &= 0x1f;
//2ms
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x30; //设置定时初值
TH0 = 0xF8; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1;
//100us
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x9C; //设置定时初值
TH1 = 0xFF; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET0 = 1;
ET1 = 0;
EA = 1;
}
//显示函数
void display(void)
{
//消隐
P2 = (P2&0x1f) | 0xe0;
P0 = 0xff;
P2 &= 0x1f;
//位选
P2 = (P2&0x1f) | 0xc0;
P0 = 1<<dspcom;
P2 &= 0x1f;
//段选
P2 = ((P2&0x1f)|0xE0);
P0 = tab[dspbuf[dspcom]];
P2 &= 0x1f;
if(++dspcom == 8)
{
dspcom = 0;
}
}
void key_proc()
{
switch(key_val)
{
case 7:
{
flag = !flag;
key_val = 20;
break;
}
case 6:
{
time = 0;
key_val = 20;
break;
}
case 5:
{
time += 60;
if (time >= 180)
{
time = 0;
}
key_val = 20;
break;
}
case 4:
{
wind++;
if (wind >= 4)
wind = 1;
key_val = 20;
break;
}
}
}
//按键扫描
void key_scanf(void)
{
static unsigned char key_st = 0;
switch(key_st){
case 0:
if((P3&0x0F) != 0x0F){
key_st = 1;
}
break;
case 1:
if((P3&0x0F) != 0x0F){
key_st = 2;
if((P3&0x0F) == 0x0E) key_val = 7;
else if((P3&0x0F) == 0x0D) key_val = 6;
else if((P3&0x0F) == 0x0B) key_val = 5;
else if((P3&0x0F) == 0x07) key_val = 4;
}
else{
key_st = 0; //按键抖动
}
break;
case 2:
if((P3&0x0F) == 0x0F){
key_st = 0;
}
else{
;
}
break;
}
}
void timer0() interrupt 1
{
static uint intr1 = 0, intr2 = 0, intr3 = 0;
display();//2ms
if (++intr1 == 500)//1s
{
intr1 = 0;
if (time > 0)
time--;
}
//300ms温度扫描
if (++intr2 == 150)
{
intr2 = 0;
flag_temp = 1;
}
//30ms检测按键状态
if (++intr3 == 15)
{
intr3 = 0;
key_scanf();
}
}
//100us * 10 = 1s
void timer1(void) interrupt 3
{
if (++pwm_count <= pwm_value)
{
P34 = 1;
}
else
{
P34 = 0;
if (++pwm_count == 10)
pwm_count = 0;
}
}
onewire.h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
onewire.c
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--)
{
signed char i = 0;
for (i = 0; i < 12; i++);
}
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}