立即注册 登录
返回首页

uid:83710的个人空间

日志

实习程序(pid算法)(改进版)

热度 1已有 1638 次阅读2015-6-25 02:32 | 程序

//main.c
 #include"iostm8s103K3.h"
#include"1602.h"
#include"ds18b20.h"
#include"pwm.h"
#include"time.h"
#include"epprom.h"

void lcd_display();
void lcd_display0();
void ir_code();
void display_flag();
main()
{
  
        asm("sim");          //关闭总中断
        clock_hsi_16mhz();  //定义时间为16MHZ
        LCD_GPIO_inint();   //定义1602的引脚
        LCD_init();         //1602初始化z
        TIM2_Init();        //三路pwm波初始化PD4,PD3,PA3.
        TIM4_Init();
       exit_init();        //外部中断使能,PC1.
    //   epprom_unlocked();
        Ir_Init();
       Ir_PWM_Init(); 
        ir_real=' ';
        set_rads=54;
        asm("rim");         //开启总中断       
      
while (1)
       {      
       lcd_display();
       ir_code(); 
   
}
}


void lcd_display0()
{
 
  if(ds1820_flag==0)
    {
     ds1820_flag=1;
     wendu_caculate();   //采集当前温度
     LCD_disp_string(0,1,"T:              ");  //lcd屏幕初始化
     LCD_disp_string(2,1,wendu_buffer);        //显示当前温度
      LCD_disp_string(7,1,"          ");  
     LCD_disp_char(8,1,ir_real);               //去抖
     if(PE_ODR&&0X20==0x20)
     LCD_disp_string(10,1,"ck");
     LCD_disp_char(13,1,ir_rads_flag+0x30);
    }
    if(cishu%500==0)
    dis_rads();
  
}
void ir_code()
{   
    Ir_Receive();
    if(IrRecFlag == 1)
    {
      ds1820_flag=0;
      IrRecAddr1 = IrRecBuff[0];
      IrRecAddr2 = IrRecBuff[1];
      IrRecData1 = IrRecBuff[2];
      IrRecData2 = IrRecBuff[3];
      IrRecFlag = 0;
     switch(IrRecData1) 
     {
       case KEY_0:ir_real=0+0X30;break;
       case KEY_1:ir_real=1+0X30;break;
       case KEY_2:ir_real=2+0X30;break;
       case KEY_3:ir_real=3+0X30;break;
       case KEY_4:ir_real=4+0X30;break;
       case KEY_5:ir_real=5+0X30;break;
       case KEY_6:ir_real=6+0X30;break;
       case KEY_7:ir_real=7+0X30;break;
       case KEY_8:ir_real=8+0X30;break;
       case KEY_9:ir_real=9+0X30;break;
       case prev:ir_real='P';break;
       case next:ir_real='N';pid_add_flag2();break;
       case play_pause:ir_real='p';display_flag();break;
       case chdel:ir_real='a';del_rad();break;
       case ch:ir_real='C';set_rad();break;
       case chadd:ir_real='A';add_rad();break;
       case del:ir_real='d';break;
       case add:ir_real='D'; break;
       case eq:ir_real='Q';break;
       case add100: ir_real='O'; break;
       case add200:ir_real='T';break;
     default:ir_real=' ';break;
     }
    }
}


void display_flag()
{
  ++dis_flag;
  if(dis_flag==3)
    dis_flag=0;
}

void lcd_display()
{
   switch(dis_flag)
  {
  case 0:lcd_display0();break;
  case 1:lcd_display1();break;
  case 2:lcd_display2();break;
  default:lcd_display0();break;
  }
}


//1602.h
#include"canshu.h"

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - 定义子程序函数
void LCD_init(void); // - - 初始化LCD1602函数
void LCD_write_command(uchar command); // - - 向LCD1602写指令函数
void LCD_write_data(uchar dat); // - - 向LCD1602写数据函数
void LCD_set_xy(uchar x,uchar y); // - - 设置LCD1602显示位置 X(0-16),y(1-2)
void LCD_disp_char(uchar x,uchar y,uchar dat); // - - 在LCD1602上显示一个字符
void LCD_disp_string(uchar X,uchar Y,uchar *s); // - - 在LCD1602上显示一个字符串
//void LCD_check_busy(void);//检查忙函数。我没用到此函数,因为通过率极低。
void LCD_delay_10us(uint n); // - - 10微秒的延时子程序
void LCD_delay_50us(uint n); // - - 50微秒的延时子程序
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

void clock_hsi_16mhz(void)
{
        CLK_ICKR|=0x01;      //开启内部HSI
while(!(CLK_ICKR&0x02));//HSI准备就绪
CLK_SWR=0xe1;        //HSI为主时钟源
CLK_CKDIVR=0x00;     //HSI不分频
}


// - - 初始化LCD1602
void LCD_init(void)
{
LCD_delay_10us(20);
LCD_write_command(0x38); // - - 设置8位格式,2行,5x7
LCD_delay_10us(5);
LCD_write_command(0x0c); // - - 整体显示,关光标,不闪烁
LCD_delay_10us(5);
LCD_write_command(0x06); // - - 设定输入方式,增量不移位
LCD_delay_10us(5);
LCD_write_command(0x01); // - - 清除屏幕显示
LCD_delay_50us(40);
}
//********************************

// - - 向LCD1602写指令
void LCD_write_command(uchar dat)
{
LCD_delay_10us(5);
LCD_RS_LOW; // - - 指令
//LCD_RW_LOW; // - - 写入
DATAOUT=dat;
LCD_delay_10us(5);
LCD_EN_HIGH; // - - 允许
LCD_delay_10us(5);
LCD_EN_LOW;
}

// - - 向LCD1602写数据
void LCD_write_data(uchar dat) 
{
LCD_delay_10us(5);
LCD_RS_HIGH;// - - 数据
//LCD_RW_LOW;// - - 写入
DATAOUT=dat;
LCD_delay_10us(5);
LCD_EN_HIGH;// - - 允许
LCD_delay_10us(5);
LCD_EN_LOW;
}

// - - 设置显示位置
void LCD_set_xy(uchar x,uchar y)
{
  uchar address;
  if(y==1)
  {
    address=0x80+x; // - - 第一行位置
  } else {
    address=0xc0+x; // - - 第二行位置
  }
    LCD_delay_10us(5);
    LCD_write_command(address);
}

// - - 显示一个字符函数
void LCD_disp_char(uchar x,uchar y,uchar dat) // - - LCD_disp_char(0,1,0x38); // - - 显示8
{
    LCD_set_xy(x,y);
    LCD_delay_10us(5);
    LCD_write_data(dat);
}

// - - 显示一个字符串函数
void LCD_disp_string(uchar x,uchar y,uchar *s)
{
  LCD_set_xy(x,y);
  LCD_delay_10us(5);
  while(*s!='\0')
  {
    LCD_write_data(*s);
    s++;
  }
}

//********************************
/*******检查忙函数*************
void LCD_check_busy() //实践证明,在我的LCD1602上,检查忙指令通过率极低,以
{  //至于不能正常使用LCD。因此我没有再用检查忙函数。而使
  do   //用了延时的方法,延时还是非常好用的。我试了一下,用
  { LCD_E=0;   //for循环作延时,普通指令只要1次循就可完成。清屏指令
    LCD_RS=0;                 //要用200次循环便能完成。   
    LCD_RW=1;
    LCD_DB=0xff;
    LCD_E=1;
  }while(LCD_DB^7==1);
******************************/

void LCD_delay_10us(uint n) // - - 10微秒的延时子程序
  uint i,j;
  for(i=n;i>0;i--)
    for(j=4;j>0;j--);  

void LCD_delay_50us(uint n) // - - 50微秒的延时子程序
  uint i,j;
  for(i=n;i>0;i--)
    for(j=22;j>0;j--);  

void LCD_GPIO_inint()
{
     PA_DDR=0x0e;
     PA_CR1=0x0e;
     PA_CR2=0x0e;
     
     PB_DDR=0xff;
     PB_CR1=0xff;
     PB_CR2=0xff;
     
     PE_DDR=0x20;
     PE_CR1=0x20;
     PE_CR2=0x20;
     PE_ODR&=0Xdf;
     
}


void dis_rads()
{
  
  
        {
        ulong pinjun_rads=0;
        uchar i;
        uint big_rads,small_rads;
        for(i=0;i<9;i++)
        {
          if(last_rads[i]>last_rads[i+1])
          {
            big_rads=last_rads[i];
            last_rads[i]=last_rads[i+1];
            last_rads[i+1]=big_rads;          
          } 
          
          for(i=0;i<8;i++)
          {
            if(last_rads[i]<last_rads[i+1])
            {
              small_rads=last_rads[i];
              last_rads[i]=last_rads[i+1];
              last_rads[i+1]=small_rads;
            }
          }
          
          for(i=1;i<9;i++)
           pinjun_rads+= last_rads[i];
           pinjun_rads/=8;
           real_rads=(uint)(pinjun_rads);
        }
      }
  
  uchar real_rad[4],set_rad[4];
  LCD_disp_string(0,0,"S:              ");
  real_rad[0]=real_rads/1000+0x30;
  real_rad[1]=real_rads%1000/100+0x30;
  real_rad[2]=real_rads%1000%100/10+0x30;
  real_rad[3]=real_rads%10+0x30;
  
  set_rad[0]=set_rads/1000+0x30;
  set_rad[1]=set_rads%1000/100+0x30;
  set_rad[2]=set_rads%1000%100/10+0x30;
  set_rad[3]=set_rads%10+0x30;
  if(real_rads<1000)real_rad[0]=' ';
  if(real_rads<100)real_rad[1]=' ';
  if(real_rads<10)real_rad[2]=' ';
  if(set_rads<1000)set_rad[0]=' ';
  if(set_rads<100)set_rad[1]=' ';
  if(set_rads<10)set_rad[2]=' ';
  
  LCD_disp_string(2,0,set_rad);
  
  LCD_disp_string(6,0,"r  R:     ");
  
  LCD_disp_string(11,0,real_rad);
  LCD_disp_char(15,0,'r');


//ds18b20.h
#include"canshu.h"

/******** STM8S-Discovery DS18B20 Test ********
* 版本.........: 1.0
* 作者.........: 陈利栋
* 目标.........: STM8S105C6
* 文件名.......: main.c
* 编译器.......: IAR for STM8 V1.1
* 创建时间.....: 2010.09.10
* 最后修改.....: 2010.09.10
**********************************************/

uchar wendu_buffer[5]={'0','0','.','0','C'};
unsigned char rom_code[8];
unsigned char const laseredrom[2][8]=
{
   0x28,0xff,0x57,0x97,0x66,0x14,0x02,0xf4,
  0x28,0xff,0xc9,0xd2,0x69,0x14,0x04,0x05,
};
uchar id[maxnum][8];
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;
    }
}


void DS18B2_WRITEBIT(uchar data)
{
    DS18B20_DQ_OUT;
     DS18B20_DQ_LOW;
       if (data & 0x01)
        {
            DS18B20_DQ_HIGH;
        }
        _delay_us(60);
       DS18B20_DQ_HIGH;
       
}

unsigned char DS18B20_2BITS(void)
{
  unsigned char i,data=0;
  for(i=0;i<2;i++)
  {
     DS18B20_DQ_OUT;
     DS18B20_DQ_LOW;
     _delay_us(5);
     data<<=1;
      DS18B20_DQ_HIGH;
      DS18B20_DQ_IN;
       if (DS18B20_DQ_VALUE)
         data|=0x01;
       DS18B20_DQ_OUT; 
        DS18B20_DQ_HIGH;
        _delay_us(60);
  }
  return data;
}

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;
}

float DS18B20_ReadTemperature1(unsigned char j)
{
    unsigned char i,temp = 0;
    float t = 0;
    
    DS18B20_Init();
    DS18B20_WriteByte(0x55);
    for(i=0;i<8;i++)
    DS18B20_WriteByte(laseredrom[j][7-i]);
    DS18B20_WriteByte(0x44);
      
    DS18B20_Init();
    DS18B20_WriteByte(0x55);
    for(i=0;i<8;i++)
    DS18B20_WriteByte(laseredrom[j][7-i]);
    
    DS18B20_WriteByte(0xbe);

    temp = DS18B20_ReadByte();
    t = (((temp & 0xf0) >> 4) + (temp & 0x07) * 0.125); 
    temp = DS18B20_ReadByte();
    t += ((temp & 0x0f) << 4);
    return t;
}

float DS18B20_read(unsigned char i)
{
  unsigned char j,temp = 0;
  float t = 0;
    DS18B20_Init();
    DS18B20_WriteByte(0xcc);
    DS18B20_WriteByte(0x44);
    DS18B20_Init();
    DS18B20_WriteByte(0x55);
    for(j=0;j<8;j++)
    {
       DS18B20_WriteByte(id[i][j]);
    }
     DS18B20_WriteByte(0xbe);
     temp = DS18B20_ReadByte();
    t = (((temp & 0xf0) >> 4) + (temp & 0x07) * 0.125); 
    temp = DS18B20_ReadByte();
    t += ((temp & 0x0f) << 4);
    
    return t;
}



void read_rom_cmd(void)
{
  unsigned char i;
    DS18B20_Init();
    DS18B20_WriteByte(0x33); 
    for(i=0;i<8;i++)
    rom_code[i]= DS18B20_ReadByte(); 
}


void wendu_caculate()
{
    int dis_wendu;
    wendu=DS18B20_ReadTemperature();
    dis_wendu=(int)(wendu*10);
    wendu_buffer[0]=dis_wendu/100+0x30;
    wendu_buffer[1]=dis_wendu%100/10+0x30;
    wendu_buffer[3]=dis_wendu%10+0x30;
    if(dis_wendu<100)
      wendu_buffer[0]=' ';
     wendu_buffer[2]='.';
    if(dis_wendu>1000)
    {
    wendu_buffer[0]=dis_wendu/1000+0x30;
    wendu_buffer[1]=dis_wendu%1000/100+0x30;
    wendu_buffer[2]=dis_wendu%1000%100/10+0x30;
    wendu_buffer[3]=' ';
    }
    if( dis_wendu>=330)
    {
      PE_ODR&=0Xdf;
      PE_ODR|=0X20;
    }
    else 
      PE_ODR&=0Xdf;




//time.h
#include"canshu.h"
#include"1838.h"

//计数器模块
    void TIM4_Init()
    {
      TIM4_IER=0x01;//启动中断
      TIM4_EGR=0X01;//允许时能更新事件
      TIM4_PSCR=0x07;// 计数器时钟=主时钟/128=16MHZ/128=125KHZ
      TIM4_ARR=249;//自动装载值;定时周期=125khz/250≈2ms
      TIM4_CNTR=249;//计数器初值
      TIM4_CR1=0x01;//时能计数器
    }


#pragma vector=TIM4_OVR_UIF_vector//0x19
__interrupt void TIM4_OVR_UIF_IRQHandler(void)//对应IAP的中断地址:0x8060
{
      ++cishu;
      
      TIM4_SR=0x00;     
      if(cishu==29999)
      {
        cishu_flag=1;
        cishu=0;
        minute++;
       ds1820_flag=0;
      }
      if(cishu%100==0)
       pid_caculate(); 
        
}

void pid_caculate()
{
   int ppk,ppi,ppd;
   ppk=(int)((long)(((int)(pk*100))*(pid_error))/100);
   ppi=(int)((long)(((int)(pi*100))*(pid_error-pid_error1))/100);
   ppd=(int)((long)(((int)(pd*100))*(pid_dt1-pid_dt2))/100);
   pid_out+=ppk+ppi+ppd;
   if(pid_out>2000)pid_out=2000;
   if(pid_out<1000)pid_out=1000;
   TIM2_CCR1H =pid_out/256;
   TIM2_CCR1L = pid_out%256;


//canshu.h
#include"iostm8s103K3.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long

uchar cishu_flag;
int cishu;
uint minute;
uint last_ms,now_ms;
uint  last_rads[10],now_rads;
uint last_radss,last_radsss;
uint real_rads; 
int set_rads;


uchar now_nus,last_nus;
int chaju_ms,chaju_nus;
uchar rads_flag;
uchar ds1820_flag;
uchar exit_flag;

uchar ir_real;
uchar ir_rads_flag;
uchar dis_flag;
char pid_flag1,pid_flag2;
int pid_error,pid_error1;
int pid_out;
int pid_dt1,pid_dt2;

float pk,pi,pd;

float wendu;
//1602参数设计
#define  LCD_RS_OUT         PA_DDR_DDR1 = 1   //输出
#define  LCD_RW_OUT         PA_DDR_DDR2 = 1   //输出
#define  LCD_E_OUT          PA_DDR_DDR3 = 1   //输出

#define LCD_RS_HIGH         PA_ODR_ODR1 = 1   //拉高
#define LCD_RS_LOW          PA_ODR_ODR1 = 0   //拉低
#define LCD_RS_PULL_UP      PA_CR1_C11  = 1   //上拉
#define LCD_RS_FLOATING     PA_CR1_C11  = 0   //浮空
#define LCD_RS_HIGH_SPEED   PA_CR2_C21  = 1   //高速
#define LCD_RS_LOW_SPEEND   PA_CR2_C21  = 0   //低速

/*
#define LCD_RW_HIGH         PA_ODR_ODR2 = 1   //拉高
#define LCD_RW_LOW          PA_ODR_ODR2 = 0   //拉低
#define LCD_RW_PULL_UP      PA_CR1_C12  = 1   //上拉
#define LCD_RW_FLOATING     PA_CR1_C12  = 0   //浮空
#define LCD_RW_HIGH_SPEED   PA_CR2_C22  = 1   //高速
#define LCD_RW_LOW_SPEEND   PA_CR2_C22  = 0   //低速
*/
#define LCD_EN_HIGH         PA_ODR_ODR2 = 1   //拉高
#define LCD_EN_LOW          PA_ODR_ODR2 = 0   //拉低
#define LCD_EN_PULL_UP      PA_CR1_C12  = 1   //上拉
#define LCD_EN_FLOATING     PA_CR1_C12  = 0   //浮空
#define LCD_EN_HIGH_SPEED   PA_CR2_C22  = 1   //高速
#define LCD_EN_LOW_SPEEND   PA_CR2_C22  = 0   //低速

#define  DATAOUT            PB_ODR 


//ds18b20宏定义
#define DS18B20_DQ_OUT          PF_DDR_DDR4 = 1   //输出
#define DS18B20_DQ_IN           PF_DDR_DDR4 = 0   //输入
#define DS18B20_DQ_HIGH         PF_ODR_ODR4 = 1   //拉高
#define DS18B20_DQ_LOW          PF_ODR_ODR4 = 0   //拉低
#define DS18B20_DQ_PULL_UP      PF_CR1_C14  = 1   //上拉
#define DS18B20_DQ_FLOATING     PF_CR1_C14  = 0   //浮空
#define DS18B20_DQ_PUSH_PULL    PF_CR1_C14  = 1   //推挽
#define DS18B20_DQ_OPEN_DRAIN   PF_CR1_C14  = 0   //开漏
#define DS18B20_DQ_VALUE        PF_IDR_IDR4       //DQ值
#define maxnum 2


//1838解码代码
#define KEY_0     0x16                 //键0
#define KEY_1     0x0C                 //键1
#define KEY_2     0x18                 //键2
#define KEY_3     0x5E                 //键3
#define KEY_4     0x08                 //键4
#define KEY_5     0x1C                 //键5
#define KEY_6     0x5A                 //键6
#define KEY_7     0x42                 //键7
#define KEY_8     0x52                 //键8
#define KEY_9     0x4A                 //键9
#define prev      0x44                 //电源
#define next       0x40                 //模式
#define play_pause 0x43                 //静音
#define chdel      0x45                //模式
#define ch        0x46  
#define chadd       0x47                 //模式
#define del       0x07 
#define add       0x15 
#define eq        0x09 
#define add100     0x19 
#define add200      0x0d

//1838.h
#include"canshu.h"


uchar IrRecStep = 0;                             //接收步骤
uchar IrIndex = 0;                                //接收位数
uchar IrRecFlag = 0;                             //接收完标志
uchar IrRecBuff[4];                               //接收缓冲区
uchar IrRecAddr1;                                //红外地址码
uchar IrRecAddr2;
uchar IrRecData1;                                //红外数据码
uchar IrRecData2;
uint IrCycle = 0;                                  //红外周期
uint IrHigh = 0;                                   //占空比
const uchar IrCode[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//--------引导码低电平范围------------------
#define IrHeadLow_Max       2300            //2300*4 = 9200us
#define IrHeadLow_Min        2100            //2100*4 = 8400us
//--------引导码高电平范围------------------
#define IrHeadHigh_Max      1250            //1250*4 = 5000us
#define IrHeadHigh_Min       1050            //1050*4 = 4200us
//--------数据0的周期范围-------------------
#define IrData00_Max         300             //300*4 = 1200us
#define IrData00_Min          260             //260*4 = 1040us
//--------数据1的周期范围-------------------
#define IrData10_Max         580             //580*4 = 2320us
#define IrData10_Min          540             //540*4 = 2160us
//--------数据0的占空比(高电平)范围---------
#define IrData0_Max          160             //160*4 = 640us
#define IrData0_Min           120             //120*4 = 480us
//--------数据1的占空比(高电平)范围---------
#define IrData1_Max          440             //440*4 = 1760us
#define IrData1_Min           400             //400*4 = 1600us
//----------------------------------------------------------
#define REMOTE_CLK_DIV       63              //63+1=64----16Mh/64=4us
#define REMOTE_ICF_FILTER   0x30
//延时程序

void add_rad();
void set_rad();
void del_rad();
void lcd_display1();
void lcd_display2();

void Delay_ms( uint ms )
  uint i,j;
  for( j=0; j<ms; )
   { 
    for( i=0; i<1000; i++ )
    {;} 
  }
}
//红外接收端口初始化
void Ir_Init(void)
{
  PC_DDR_DDR1 = 0;       //PC1为输入
  PC_CR1_C11 = 1;
  PC_CR2_C21 = 0;
}
//使用TIM1的PWM输入捕获
void Ir_PWM_Init(void)
  TIM1_PSCRH = 0;
  TIM1_PSCRL = REMOTE_CLK_DIV;
  TIM1_CCER1 &= 0xee;//禁止输入捕获1,2
  TIM1_CCMR1 |= (REMOTE_ICF_FILTER + 0x01);// ch1到ti1fp1
  TIM1_CCER1 &= 0xec;//ch1 上升沿触发
  TIM1_CCMR2 |= (REMOTE_ICF_FILTER + 0x02);// ch2选择 ti1fp2上
  TIM1_CCER1 |= 0x20;//ch1 下降沿触发 ic2
  TIM1_SMCR |= 0x54;//选源触发源和触发方式 复位
  TIM1_CCER1 |= 0x11;//使能输入捕获1,2
  TIM1_CR1 |= 0x05;
}
//红外接收程序
void Ir_Receive(void)
{
  switch(IrRecStep)
  {
  case 0:
          IrIndex = 0;
          if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
          {
            IrHigh = (uint)(TIM1_CCR2H); 
            IrHigh = (IrHigh << 8) + TIM1_CCR2L;  //IrHigh占空比
            IrCycle = (uint)(TIM1_CCR1H);
            IrCycle = (IrCycle << 8) + TIM1_CCR1L;  //IrCycle周期
            //是否在引导码低电平范围内
            if (((IrCycle - IrHigh) < IrHeadLow_Max)&&((IrCycle - IrHigh) > IrHeadLow_Min))
            {
              IrRecStep = 1;
              TIM1_SR1_CC1IF = 0;
              TIM1_SR1_CC2IF = 0;
              TIM1_SR2_CC1OF = 0;
              TIM1_SR2_CC2OF = 0;
              TIM1_SR1_UIF = 0;
              
              IrRecBuff[0] = 0;
              IrRecBuff[1] = 0;
              IrRecBuff[2] = 0;
              IrRecBuff[3] = 0;
            }
          }
          break;
  case 1:
          if ((TIM1_SR2_CC1OF==1) || (TIM1_SR2_CC2OF==1) || (TIM1_SR1_UIF==1))
          { 
            IrRecStep = 0;
          }
          else
          { 
            if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
            { 
              IrHigh = (uint)(TIM1_CCR2H); 
              IrHigh = (IrHigh << 8) + TIM1_CCR2L;
              IrCycle = (uint)(TIM1_CCR1H); 
              IrCycle = (IrCycle << 8) + TIM1_CCR1L;
              //是否在引导码高电平范围内
              if ((IrHigh < IrHeadHigh_Max)&&(IrHigh > IrHeadHigh_Min))
              {
                IrRecStep = 2;
              }
            }
          }
          break;
  case 2:
          if ((TIM1_SR2_CC1OF==1) || (TIM1_SR2_CC2OF==1) || (TIM1_SR1_UIF==1))
          { 
            IrRecStep = 0;
          }
          else
          { 
            if ((TIM1_SR1_CC1IF == 1)&&(TIM1_SR1_CC2IF == 1))
            { 
              IrHigh = (uint)(TIM1_CCR2H); 
              IrHigh = (IrHigh << 8) + TIM1_CCR2L;
              IrCycle = (uint)(TIM1_CCR1H); 
              IrCycle = (IrCycle << 8) + TIM1_CCR1L;
              //周期是否在数据0范围内
              if ((IrCycle > IrData00_Min)&&(IrCycle < IrData00_Max))
              {
                //高电平是否在数据0范围内
                if ((IrHigh > IrData0_Min)&&(IrHigh < IrData0_Max))
                {
                  IrIndex++;
                }
                else
                {
                  IrRecStep = 0;
                }
              }
              //周期是否在数据1范围内
              else if ((IrCycle > IrData10_Min)&&(IrCycle < IrData10_Max))
              {
                //高电平是否在数据1范围内
                if ((IrHigh > IrData1_Min)&&(IrHigh < IrData1_Max))
                {
                  IrRecBuff[IrIndex >> 3] |= IrCode[IrIndex & 0x07];
                  IrIndex++;
                }
                else
                {
                  IrRecStep = 0;
                }
              }
              else
              {
                IrRecStep = 0;
              }
              if(IrIndex >= 32)
              {
                IrRecStep = 0;
                IrRecFlag = 1;
              }
            }
          }
          break;
  }
}
      
//时钟初始化
void CLK_Init(void)
{
  CLK_ECKR=0x03;//外部时钟寄存器 外部时钟准备就绪,外部时钟开
  CLK_SWCR=0x02;//切换控制寄存器 使能切换机制
  CLK_SWR=0xB4;//主时钟切换寄存器 选择HSE为主时钟源*/
  while (!(CLK_SWCR & 0x08));  
  CLK_CSSR=0x01;//时钟安全系统寄存器    
}

//初始化
void Devices_Init(void)
{
  Delay_ms(200);
  CLK_Init(); 
  Ir_Init();
  Ir_PWM_Init();
}



void set_rad()
{
  if(dis_flag==0)
  {
  ++ir_rads_flag;
  if(ir_rads_flag==4)
    ir_rads_flag=0;
}
  if(dis_flag==2)
  {
    ++pid_flag1;
    if(pid_flag1==4)
      pid_flag1=0;
  }
}

void add_rad()
{
    if(dis_flag==0)
  {
  switch(ir_rads_flag)
  {
  case 0:set_rads+=1;break;
  case 1:set_rads+=10;break;
  case 2:set_rads+=100;break;
  case 3:set_rads+=1000;break;
  default:break;
  }
  if(set_rads>=10000)set_rads=9999;
 }
 
  if(dis_flag==2)
  {  
    switch(pid_flag1)
    {
    case 0:
     switch(pid_flag2)
     {
     case 0:pk+=0.01;break;
     case 1:pi+=0.01;break;
     case 2:pd+=0.01;break;
     default:break;
     }
      break;
    case 1:
       switch(pid_flag2)
     {
     case 0:pk+=0.1;break;
     case 1:pi+=0.1;break;
     case 2:pd+=0.1;break;
     default:break;
     }
      break;
    case 2:
        switch(pid_flag2)
     {
     case 0:pk+=1;break;
     case 1:pi+=1;break;
     case 2:pd+=1;break;
     default:break;
     }
      break;
    case 3:
        switch(pid_flag2)
     {
     case 0:pk+=10;break;
     case 1:pi+=10;break;
     case 2:pd+=10;break;
     default:break;
     }
      break;
    default:break;
    }
    if(pk>9999)pk=9999;
    if(pi>9999)pi=9999;
    if(pd>9999)pd=9999;

  }
}
void del_rad()
{
  if(dis_flag==0)
  {
    switch(ir_rads_flag)
  {
  case 0:set_rads-=1;break;
  case 1:set_rads-=10;break;
  case 2:set_rads-=100;break;
  case 3:set_rads-=1000;break;
  default:break;
  }
  if(set_rads<1)set_rads=0;
}

 if(dis_flag==2)
  {

    switch(pid_flag1)
    {
    case 0:
     switch(pid_flag2)
     {
     case 0:pk-=0.01;break;
     case 1:pi-=0.01;break;
     case 2:pd-=0.01;break;
     default:break;
     }
      break;
    case 1:
       switch(pid_flag2)
     {
     case 0:pk-=0.1;break;
     case 1:pi-=0.1;break;
     case 2:pd-=0.1;break;
     default:break;
     }
      break;
    case 2:
        switch(pid_flag2)
     {
     case 0:pk-=1;break;
     case 1:pi-=1;break;
     case 2:pd-=1;break;
     default:break;
     }
      break;
    case 3:
        switch(pid_flag2)
     {
     case 0:pk-=10;break;
     case 1:pi-=10;break;
     case 2:pd-=10;break;
     default:break;
     }
      break;
    default:break;
    }
    
    if(pk<0)pk=0;
    if(pi<0)pi=0;
    if(pd<0)pd=0;

  }
}


void pid_add_flag2()
{
  if(dis_flag==2)
  {
  ++pid_flag2;
  if(pid_flag2>=3)
    pid_flag2=0;
}
}


void lcd_display1()
{
  if(cishu%500==0)
  {
  uchar dis_t[5];
  uchar time_dis[8];
  dis_t[0]=t/10000+0x30;
  dis_t[1]=t%10000/1000+0x30;
  dis_t[2]=t%10000%1000/100+0x30;
  dis_t[3]=t%10000%1000%100/10+0x30;
  dis_t[4]=t%10+0x30;
  if(t<10000)dis_t[0]=' ';
  if(t<1000)dis_t[1]=' ';
  if(t<100)dis_t[2]=' ';
  
  time_dis[0]=minute/60/10+0x30;
  time_dis[1]=minute/60%10+0x30;
  time_dis[2]=':';
  time_dis[3]=minute%60/10+0x30;
  time_dis[4]=minute%60%10+0x30;
  time_dis[5]=':';
  time_dis[6]=t*2/1000/10+0x30;
  time_dis[7]=t*2/1000%10+0x30;
  if(minute<600)time_dis[0]=' ';
  if(minute<60)
  {
    time_dis[1]=' ';
    time_dis[2]=' ';
  }
    if(minute<10)time_dis[3]=' ';
  if(t<5000)time_dis[3]=' ';
  
  LCD_disp_string(0,1,"t:              "); 
  LCD_disp_string(2,1,dis_t);
  LCD_disp_char(8,1,ir_real);  
  LCD_disp_string(0,0,"time:           ");
  LCD_disp_string(5,0,time_dis);
   LCD_disp_string(13,0,"   ");
   LCD_disp_string(9,1,"      ");
  }
}


void lcd_display2()
{
  if(cishu%500==0)
  {
  uchar p[5],i[5],d[5];
  int pp,ii,dd;
  pp=(int)(pk*100);
  ii=(int)(pi*100);
  dd=(int)(pd*100);
   p[0]=pp/1000+0x30;
   p[1]=pp%1000/100+0x30;
   p[2]='.';
   p[3]=pp%1000%100%10+0x30;
   p[4]=pp%10+0x30;
   
   i[0]=ii/1000+0x30;
   i[1]=ii%1000/100+0x30;
   i[2]='.';
   i[3]=ii%1000%100%10+0x30;
   i[4]=ii%10+0x30;
   
   d[0]=dd/1000+0x30;
   d[1]=dd%1000/100+0x30;
   d[2]='.';
   d[3]=dd%1000%100%10+0x30;
   d[4]=dd%10+0x30;
   
   if(pp<1000)p[0]=' ';
   if(ii<1000)i[0]=' ';
   if(dd<1000)d[0]=' ';
   LCD_disp_string(0,1,"P:              ");
   LCD_disp_string(2,1,p);
   LCD_disp_string(7,1,"  ");
   LCD_disp_string(9,1,"I:     ");
   LCD_disp_string(11,1,i);
   LCD_disp_string(0,0,"D:              ");
   LCD_disp_string(2,0,d);
   LCD_disp_char(7,0,' ');
   LCD_disp_char(8,0,ir_real);  
   LCD_disp_string(9,0,"       ");
   LCD_disp_char(10,0,pid_flag1+0x30);
   switch(pid_flag2)
   {
   case 0: LCD_disp_char(12,0,'P');break;
   case 1:LCD_disp_char(12,0,'I');break;
   case 2:LCD_disp_char(12,0,'D');break;
   default:LCD_disp_char(12,0,' ');break;
   }
  }
}
 //pwm.h
#include"canshu.h"
void pid_caculate();
uint t;
void TIM2_Init()
{
TIM2_CCMR2 = TIM2_CCMR2 | 0x70;// Output modePWM2.         
                                //通道2被设置成比较输出方式
                                // OC2M = 111,为PWM模式2,
                                // 向上计数时,若计数器小于比较值,为无效电平
                                // 即当计数器在0到比较值时,输出为1,否则为0
TIM2_CCMR1 = TIM2_CCMR1 | 0x70;
TIM2_CCMR3 = TIM2_CCMR3 | 0x70;
TIM2_CCER1 = TIM2_CCER1 | 0x33;// CC polarity low,enable PWMoutput      */
                                // CC2P = 1,低电平为有效电平
                                // CC2E = 1,开启输出引脚               
TIM2_CCER2 = TIM2_CCER2 | 0x03; 
//初始化自动装载寄存器,决定PWM方波的频率,Fpwm=16000000/1000=16kHZ      
  TIM2_ARRH = 16000/255;
  TIM2_ARRL = 16000%255;
  
   TIM2_CCR1H =1000/255;
  TIM2_CCR1L = 1000%255;
//初始化比较寄存器,决定PWM方波的占空比            
  TIM2_CCR2H =1000/255;
  TIM2_CCR2L =1000%255;
      
  TIM2_CCR3H = 1000/256;
  TIM2_CCR3L = 1000%256;
//初始化时钟分频器为1,即计数器的时钟频率为Fmaster=4MHZ
  TIM2_PSCR =0x00;//因为用了继电器,所以哟分频,可到0x08,256分频
//启动计数
TIM2_CR1 = TIM2_CR1 | 0x01;
}

//外部中断触发
void exit_init()
{
   PC_DDR&=~0x04;
   PC_CR1|=0x04;
   PC_CR2|=0x04;
   EXTI_CR1|= 0x10;
  
   
}

#pragma vector=0x07 // 这里很关键!看下面说明。
__interrupt void EXTI_PC1(void)
{
  asm("sim"); 
  switch(EXTI_CR1)
  {
  case 0x10:EXTI_CR1=0x20;exit_flag=1;break;
  case 0x20:EXTI_CR1=0x10;exit_flag=2;break;
  default :exit_flag=0;break;
  }
 if(exit_flag==2)
 {
    t++;
   exit_flag=0;
   if(t%10==0)
   {
      ulong chaju;
      now_nus=TIM4_CNTR;
      now_ms=cishu;
     chaju_ms=now_ms-last_ms;
   if(cishu_flag==1)
   {
     cishu_flag=0;
     chaju_ms=30000+now_ms-last_ms;
   }
      chaju_nus=now_nus-last_nus;
      chaju=chaju_ms*250+chaju_nus;
      now_rads=(1250000/chaju);
      last_nus=now_nus;
      last_ms=now_ms;
      last_rads[rads_flag++]=now_rads;
      if(rads_flag==10)
        rads_flag=0;
   
    pid_error1=pid_error;
    pid_error=set_rads-now_rads;
  
     pid_dt2=pid_dt1;
     pid_dt1=pid_error-pid_error1;
     last_radsss=last_radss;
     last_radss =now_rads;
   } 
 }
 
   asm("rim"); 
}

#pragma vector=TIM2_OVR_UIF_vector
     __interrupt void TIM3_OVF_IRQHandler(void)
    {
        
         TIM2_SR1 = 0x00;
         ds1820_flag=1;
    }


//定时器2产生60s的中断
void TIM2_time()
{
     TIM2_EGR=0x01; //手动产生更新事件,重新初始化计数器,并允许产生一个更新事件    
    //设置定时器初值  
    TIM2_CNTRH=0; //不能使用TIM3_CNTR直接设值,
    TIM2_CNTRL=0;   
    //设定自动重装寄存器值      
    //这里得注意不能使用TIM2_ARR的方式进行设值,TIM2是十六位的。  
    //如TIM2_ARR=0xFA,实际上是赋给高字节了,TIM2_ARRH=0xFA,而不是想象中的赋给低字节。  
    TIM2_ARRH=0x72; //488hz 488 /29280  = 60s (1S)  
    TIM2_ARRL=0x60; //0x007d   意味着每产生一次中断时间为60S  
    TIM2_PSCR=0x0f; //预分频32275
  
    TIM2_IER=0x01; //中断允许位使能  
    TIM2_CR1=0x01; //使能计时器  

}

路过

鸡蛋
1

鲜花

握手

雷人

刚表态过的朋友 (1 人)

评论 (0 个评论)

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

返回顶部