导师居然让我们做个温度控制系统,幸好这学期自己自学了32,所以觉得这还不是件困难的事。零零散散的写了几回,还么有在做好,各个模块都调通了,所以只有收尾的工作可干了。
废话少说,先上程序。
//主函数
#include"iostm8s105k4.h"
#include"qudong.h"
#include"18b20.h"
main()
{
Init_UART2();
hex_led();
Init_Timer4();
clock_hsi_16mhz();//将系统的时钟设置为16MHZ
key_inint();//按键扫描程序,开始想用中断控制,发现效果不太好,所以改用按键扫描查询模式
TIM2_Init(); //定时器2,产生2路PWM波,一路供继电器控制热地块,另一路控制马达搅拌水
// TIM3_Init();
asm("rim");//开全局中断
while (1)
{ if(flag==1)
{
}
key_scan();
set_pwm(); //改变占空比,来调节马达和继电器的开关速率
wendu= DS18B20_ReadTemperature();//将18b20的读数读取。因为读取一个数据需要750ms,所以反应速率还是超级慢的,之前用lm35,但发现就是个啃,用不了,也许我用错了。
}
}
//驱动程序函数
#include"iostm8s105k4.h"
unsigned char HexTable[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
unsigned char code_hex[]={0x7f,0x0c,0xb6,0x9f,0xcc,0xdb,0xfb,0x0f,0xff,0xdf,0x0c,0x72};
unsigned char code_n[]={0xfb,0xf7,0xef,0xdf};
unsigned char time4_i;
unsigned long int ad_sum=500;
unsigned char set,flag;
void clock_hsi_16mhz(void)
{
CLK_ICKR|=0x01; //开启内部HSI
while(!(CLK_ICKR&0x02));//HSI准备就绪
CLK_SWR=0xe1; //HSI为主时钟源
CLK_CKDIVR=0x00; //HSI不分频
}
void hex_led(void) //设置4个共阴数码管引脚定义
{
PE_DDR|=0x20;
PE_CR1|=0x20;
PE_CR2|=0x00;
PE_ODR|=0x00;
PC_DDR|=0xFF;
PC_CR1|=0xFF;
PC_CR2|=0x00;
PC_ODR|=0x00;
PB_DDR|=0x3C;
PB_CR1|=0x3C;
PB_CR2|=0x00;
PB_ODR|=0x3C;
}
void dis_hex_led(unsigned char dat,unsigned char n)
{
PC_ODR=0x00; //由定时器4按照每2ms扫描一个数码管
PE_ODR&=0x00;
PB_ODR|=0x3c;
PB_ODR&=code_n[n];
PC_ODR=code_hex[dat];
if(n!=1)
PE_ODR&=~0x20;
else PE_ODR|=0x20;
if(ad_sum==1000)
PE_ODR&=~0x20;
}
void Init_UART2(void)
{
UART2_CR1=0x00;
UART2_CR2=0x00;
UART2_CR3=0x00;
// 设置波特率,必须注意以下几点:
// (1) 必须先写BRR2
// (2) BRR1存放的是分频系数的第11位到第4位,
// (3) BRR2存放的是分频系数的第15位到第12位,和第3位
// 到第0位
// 例如对于波特率位9600时,分频系数=2000000/9600=208
// 对应的十六进制数为00D0,BBR1=0D,BBR2=00
UART2_BRR2=0x0B;//以115.2kHz频率发送数据
UART2_BRR1=0x08;
UART2_CR2=0x08;//允许接收,发送,开接收中断
PD_DDR|=0x20;
PD_CR1|=0x40;
PD_CR2|=0x20;
PD_ODR|=0x00;
}
void UART2_sendchar(unsigned char c)//串口通信助手打开,每次发送一个数据
{
while((UART2_SR & 0x80)==0x00);
UART2_DR=c;
}
void UART2_sendhex(unsigned char dat)
{
UART2_sendchar('0');
UART2_sendchar('x');
UART2_sendchar(HexTable[dat>>4]);
UART2_sendchar(HexTable[dat&0x0f]);
UART2_sendchar(' ');
}
void UART2_sendstr(unsigned char *dat)
{
while(*dat!='\0')
{
UART2_sendchar(*dat);
dat++;
//delay2us();
}
}
void UART2_sendnum(unsigned char dat)
{
unsigned char dat_code[3];
dat_code[0]=dat/100;
dat_code[1]=dat%100/10;
dat_code[2]=dat%10;
if(dat>=100)
UART2_sendchar(HexTable[dat_code[0]]);
if(dat>=10)
UART2_sendchar(HexTable[dat_code[1]]);
UART2_sendchar(HexTable[dat_code[2]]);
}
void Init_Timer4(void)
{
TIM4_CR1=0x01;//使能计数器
//TIM4_IER=0x00;
TIM4_IER=0x01;//更新中断使能
TIM4_EGR=0x01;
TIM4_CNTR=255;//计数器值
TIM4_ARR=255;//自动重装的值
TIM4_PSCR=0x07;//分频值128分频周期4ms
}
void key_inint(void)
{
PD_DDR&=~0x85;
PD_CR1|=0x85;
PD_CR2|=0x00;
PF_DDR|=~0x10;
PF_CR1|=0x10;
PF_CR2|=0x00;
PA_DDR|=0x06;
PA_CR1|=0x06;
PA_CR2|=0x06;
PA_ODR|=0x00;
}
void delay(unsigned int i)
{
while(i--);
}
void set_key(void)
{
++set;
if(set==3)
set=0;
}
void add_key(void)
{
switch(set)
{
case 0:ad_sum+=100;break;
case 1:ad_sum+=10;break;
case 2:ad_sum+=1;break;
default: ad_sum+=0;break;
}
if(ad_sum>1000)ad_sum=1000;
}
void del_key(void)
{
switch(set)
{
case 0:ad_sum-=100;break;
case 1:ad_sum-=10;break;
case 2:ad_sum-=1;break;
default: ad_sum-=0;break;
}
if(ad_sum<200)ad_sum=200;
}
void key_scan(void)
{
if((PF_IDR&0X10)!=0X10)
{
delay(200);
if((PF_IDR&0X10)!=0X10)
{
PA_ODR^=0x02;
if(flag==0)
{
flag=1;
Init_UART2();
}
switch(flag)
{
case 1:flag=2;break;
case 2:flag=1; break;
default:flag=1;break;
}
while((PF_IDR&0X10)!=0X10);
}
}
if((PD_IDR&0x85)!=0x85)
{
delay(200);
if((PD_IDR&0x85)!=0x85)
{
switch(PD_IDR&0x85)
{
case 0x84:PA_ODR^=0x02;del_key();break;
case 0x81:PA_ODR^=0x02;add_key();break;
case 0x05:PA_ODR^=0x02;set_key();break;
default:break;
}
if(flag==2)
{
unsigned char sum_h,sum_l;
sum_h=ad_sum/100;
sum_l=ad_sum%100/10;
UART2_sendnum(sum_h);
UART2_sendnum(sum_l);
sum_l=ad_sum%10;
UART2_sendnum(sum_l);
}
while((PD_IDR&0x85)!=0x85);
}
}
}
void TIM2_Init()
{
TIM2_CCMR2 = TIM2_CCMR2 | 0x70;// Output modePWM2.
//通道2被设置成比较输出方式
// OC2M = 111,为PWM模式2,
// 向上计数时,若计数器小于比较值,为无效电平
// 即当计数器在0到比较值时,输出为1,否则为0
TIM2_CCMR1 = TIM2_CCMR1 | 0x70;
TIM2_CCER1 = TIM2_CCER1 | 0x33;// CC polarity low,enable PWMoutput */
// CC2P = 1,低电平为有效电平
// CC2E = 1,开启输出引脚
//初始化自动装载寄存器,决定PWM方波的频率,Fpwm=16000000/1000=16kHZ
TIM2_ARRH = 1000/256;
TIM2_ARRL = 1000%256;
TIM2_CCR1H = 0;
TIM2_CCR1L = 0;
//初始化比较寄存器,决定PWM方波的占空比
TIM2_CCR2H = 0;
TIM2_CCR2L = 0;
//初始化时钟分频器为1,即计数器的时钟频率为Fmaster=4MHZ
TIM2_PSCR = 0;
//启动计数
TIM2_CR1 = TIM2_CR1 | 0x01;
}
void set_pwm(void)
{
unsigned char i;
for(i=0;i<255;i++)
{
TIM2_CCR1H = 1;
TIM2_CCR1L = i;
TIM2_CCR2H = 1;
TIM2_CCR2L = i;
// delay(100);
}
// 下面的循环将占空比逐渐从50%递减到0
for(i=255;i>0;i--)
{
TIM2_CCR2H = 3;
TIM2_CCR2L = i;
TIM2_CCR1H = 3;
TIM2_CCR1L = i;
//delay(100);
}
}
#pragma vector=TIM4_OVR_UIF_vector//0x19
__interrupt void TIM4_OVR_UIF_IRQHandler(void)//对应IAP的中断地址:0x8060
{
++time4_i;
TIM4_SR=0x00;
switch(time4_i)
{
case 1:dis_hex_led(11,3);break;
case 2:
{
dis_hex_led(ad_sum/100,0);
}
break;
case 3: dis_hex_led(ad_sum%100/10,1); break;
case 4: dis_hex_led(ad_sum%10,2);time4_i=0; break;
default:time4_i=0;break;
}
//return;
}
//温度采集程序
#include"iostm8s105k4.h"
/******** STM8S-Discovery DS18B20 Test ********
* 版本.........: 1.0
* 作者.........: 陈利栋
* 目标.........: STM8S105C6
* 文件名.......: main.c
* 编译器.......: IAR for STM8 V1.1
* 创建时间.....: 2010.09.10
* 最后修改.....: 2010.09.10
**********************************************/
#define DS18B20_DQ_OUT PB_DDR_DDR0 = 1 //输出
#define DS18B20_DQ_IN PB_DDR_DDR0 = 0 //输入
#define DS18B20_DQ_HIGH PB_ODR_ODR0 = 1 //拉高
#define DS18B20_DQ_LOW PB_ODR_ODR0 = 0 //拉低
#define DS18B20_DQ_PULL_UP PB_CR1_C10 = 1 //上拉
#define DS18B20_DQ_FLOATING PB_CR1_C10 = 0 //浮空
#define DS18B20_DQ_PUSH_PULL PB_CR1_C10 = 1 //推挽
#define DS18B20_DQ_OPEN_DRAIN PB_CR1_C10 = 0 //开漏
#define DS18B20_DQ_VALUE PB_IDR_IDR0 //DQ值
float wendu;
unsigned char state;
void _delay_us(unsigned int i)
{
i *= 3;
while(--i);
}
void _delay_ms(unsigned int i)
{
while(i--)
{
_delay_us(1000);
}
}
void DS18B20_Init(void)
{
DS18B20_DQ_OUT;
DS18B20_DQ_PUSH_PULL;
DS18B20_DQ_HIGH;
_delay_us(10);
DS18B20_DQ_LOW;
_delay_us(600); //复位脉冲
DS18B20_DQ_IN;
DS18B20_DQ_PULL_UP;
_delay_us(100);
while(DS18B20_DQ_VALUE == 1);
_delay_us(400);
}
void DS18B20_WriteByte(unsigned char _data)
{
unsigned char i = 0;
DS18B20_DQ_OUT;
for (i = 0; i < 8; i++)
{
DS18B20_DQ_LOW;
_delay_us(2);
if (_data & 0x01)
{
DS18B20_DQ_HIGH;
}
_data >>= 1;
_delay_us(60);
DS18B20_DQ_HIGH;
}
}
unsigned char DS18B20_ReadByte(void)
{
unsigned char i = 0, _data = 0;
for (i = 0; i < 8; i++)
{
DS18B20_DQ_OUT;
DS18B20_DQ_LOW;
_delay_us(5);
_data >>= 1;
DS18B20_DQ_HIGH;
DS18B20_DQ_IN;
if (DS18B20_DQ_VALUE)
{
_data |= 0x80;
}
DS18B20_DQ_OUT;
DS18B20_DQ_HIGH;
_delay_us(60);
}
return _data;
}
float DS18B20_ReadTemperature(void)
{
unsigned char temp = 0;
float t = 0;
DS18B20_Init();
DS18B20_WriteByte(0xcc);
DS18B20_WriteByte(0x44);
DS18B20_Init();
DS18B20_WriteByte(0xcc);
DS18B20_WriteByte(0xbe);
temp = DS18B20_ReadByte();
t = (((temp & 0xf0) >> 4) + (temp & 0x07) * 0.125);
temp = DS18B20_ReadByte();
t += ((temp & 0x0f) << 4);
return t;
}
void TIM3_Init()
{
TIM3_EGR=0x01; //手动产生更新事件,重新初始化计数器,并允许产生一个更新事件
//设置定时器初值
TIM3_CNTRH=0; //不能使用TIM3_CNTR直接设值,
TIM3_CNTRL=0;
//设定自动重装寄存器值
//这里得注意不能使用TIM2_ARR的方式进行设值,TIM2是十六位的。
//如TIM2_ARR=0xFA,实际上是赋给高字节了,TIM2_ARRH=0xFA,而不是想象中的赋给低字节。
TIM3_ARRH=0x00; //31250 16MHz / 125 = 128000Hz (1S)
TIM3_ARRL=0x0a; //0x007d 意味着每产生一次中断时间为1MS
TIM3_PSCR=0x07; //分频128
TIM3_IER=0x01; //中断允许位使能
TIM3_CR1=0x01; //使能计时器
}
#pragma vector=TIM3_OVR_UIF_vector
__interrupt void TIM3_OVF_IRQHandler(void)
{
TIM3_SR1 = 0x00;
PA_ODR^=0x04;
}
|
|
|