新手上路
- 积分
- 26
- 金钱
- 26
- 注册时间
- 2020-4-6
- 在线时间
- 12 小时
|
/*
主函数
TIM3 用于按键扫描与时间标志位的更新
TIM1 用于输出PWM控制电热丝加热时间
PA0 DS18B20
PA8 连接继电器/同时也是DS0
*/
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "ds18b20.h"
#include "pid.h"
#include "timer.h"
#include "keyboard.h"
#include "pwm.h"
#include "heat.h"
unsigned int TEMP; //储存到小数一位的实际实时温度
unsigned int SETTEMP; //储存到小数一位的实际设置温度
unsigned int PWM=2500;
u8 flag100ms=0;
void KeyAction(unsigned char key);
void ShowTemp(void);
void ShowSetTemp(void);
void ShowPWM(void);
int main(void)
{
unsigned char flag500ms=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置系统中断优先级分组2
delay_init(); //初始化延时函数
uart_init(9600); //初始化串口波特率为115200
LED_Init(); //初始化LED
LCD_Init();
TIM3_Int_Init(10-1,8400-1); //分频系数8400 计数频率10KHz 计数到10溢出 每1Ms产生中断
TIM1_PWM_Init(10000-1,8400-1);
KEY_Init();
PID_Init();
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(30,10,200,16,16,"STM32F1 MINI");
LCD_ShowString(30,30,200,16,16,"2020/4/27");
while(DS18B20_Init()) //DS18B20初始化
{
LCD_ShowString(30,50,200,16,16,"SENSOR Error");
delay_ms(200);
LCD_Fill(30,50,239,130+16,WHITE);
delay_ms(200);
}
LCD_ShowString(30,50,200,16,16,"SENSOR OK");
POINT_COLOR=BLUE; //设置字体为蓝色
LCD_ShowString(30,70,200,16,16,"TEMP: . C");
LCD_ShowString(30,90,200,16,16,"SET : . C");
LCD_ShowString(30,110,200,16,16," WM : /9999");
SETTEMP=250; //设定目标温度
LCD_DrawLine(0,900-(SETTEMP/2),300,900-(SETTEMP/2));
ShowSetTemp();
ShowPWM();
TIM_SetCompare1(TIM1,PWM); //最大为10000控制占空比
while(1)
{
if(flag100ms) //每100ms更新一次实时温度
{
flag100ms=0;
flag500ms++;
if(flag500ms==5)
{
flag500ms=0;
ShowTemp(); //500ms测量一次温度
PWM=PID_realize();
TIM_SetCompare1(TIM1,PWM);
ShowPWM();
}
}
delay_ms(10);
}
}
/****************************************************************************************/
void ShowSetTemp(void)
{
LCD_ShowNum(30+40+8,90,SETTEMP/10,2,16); //显示正数部分
LCD_ShowNum(30+40+32,90,SETTEMP%10,1,16); //显示小数部分
}
void ShowPWM(void)
{
LCD_ShowNum(30+40+8,110,PWM,4,16);
}
void ShowTemp(void)
{
static int x=0;
short temperature;
{
temperature=DS18B20_Get_Temp();
TEMP=temperature;
LCD_ShowNum(30+40+8,70,temperature/10,2,16); //显示正数部分
LCD_ShowNum(30+40+32,70,temperature%10,1,16); //显示小数部分
//给当前温度打点
x++;if(x>=300)x=0;
LCD_DrawPoint(x,900-(TEMP/2));
}
}
void KeyAction(unsigned char key)
{
switch(key)
{
case 1 ED0=0;break;
case 2 ED0=1;break;
case 3 ED0=~LED0;break;
case 4 ED0=~LED0;break;
default:break;
}
}
/*
pid函数
*/
#include "pid.h"
#include "lcd.h"
extern unsigned int TEMP; //储存到小数一位的实际实时温度
extern unsigned int SETTEMP; //储存到小数一位的实际设置温度
struct PID pid;
void PID_Init(void) //因为有储存,因此用ReadPID()代替
{
pid.Set=SETTEMP;
pid.Actual=TEMP;
pid.err=0;
pid.err_last=0;
pid.Kp=50; //实际为除1倍
pid.Ki=100; //实际为除1000倍
pid.Kd=350; //实际为除1倍
pid.Kout=900; //偏移值
pid.voltage=0;
pid.integral=0;
LCD_ShowNum(170,10,pid.Kp,3,16);
LCD_ShowNum(170,30,pid.Ki,3,16);
LCD_ShowNum(170,50,pid.Kd,3,16);
LCD_ShowNum(170,70,pid.Kout,3,16);
}
int PID_realize(void)
{
int t;
pid.Set = SETTEMP; //设定值
pid.Actual = TEMP; //实际值
pid.err = pid.Set - pid.Actual; //差值
pid.integral = pid.integral + pid.err;
//LCD_ShowNum(30+60+12,240,pid.integral,6,24);
pid.voltage = pid.Kp*pid.err //设定值与实际的偏差
+ pid.Ki*pid.integral/1000 //历史累计偏差
+ pid.Kd*(pid.err-pid.err_last) //本次偏差与上次偏差比较
+ pid.Kout; //最终计算值
pid.err_last = pid.err;
t=pid.voltage;
if(t>9999) t=9998;
else if(t<0) t=2;
return t;
}
/*
pwm函数
*/
#include "pwm.h"
#include "led.h"
//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM1_PWM_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// 使能TIM1时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); //使能GPIO外设时钟
//设置该引脚为复用输出功能,输出TIM1 CH1的PWM脉冲波形
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 80K
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 不分频
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIM1的时间基数单位
TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //③允许更新中断
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
//TIM_OCInitStructure.TIM_Pulse = 0; //设置待装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
//TIM_CtrlPWMOutputs(TIM1,ENABLE); //MOE 主输出使能
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); //CH1预装载使能
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_Cmd(TIM1, ENABLE); //使能TIM1
}
|
|