⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 arm7 sample code, some demo for arm7 of linux
💻 C
字号:
/****************************************Copyright (c)**************************************************
**                               Guangzhou ZHIYUAN electronics Co.,LTD.
**                                     
**                                 http://www.embedtools.com
**
**--------------File Info-------------------------------------------------------------------------------
** File Name:          Main.c
** Last modified Date: 2006-11-18
** Last Version:       v1.0
** Description:        PID算法控制直流电机主文件
** 
**------------------------------------------------------------------------------------------------------
** Created By:         Zhou Shaogang
** Created date:       2006-11-18
** Version:            v1.0
** Descriptions:
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
********************************************************************************************************/

#include "Config.H"
        
/************************* GPIO 定义 *************************/
/*************************************************************/
#define LED_PIN1     GPIO_PIN_4
#define LED_PIN2     GPIO_PIN_5
#define LED1_ON()    GPIOPinWrite(GPIO_PORTB_BASE, LED_PIN1, ~LED_PIN1)
#define LED1_OFF()   GPIOPinWrite(GPIO_PORTB_BASE, LED_PIN1, LED_PIN1)
#define LED2_ON()    GPIOPinWrite(GPIO_PORTB_BASE, LED_PIN2, ~LED_PIN2)
#define LED2_OFF()   GPIOPinWrite(GPIO_PORTB_BASE, LED_PIN2, LED_PIN2)

#define BUZ_PIN      GPIO_PIN_2   //PB2
#define BUZ_ON()     GPIOPinWrite(GPIO_PORTB_BASE, BUZ_PIN, ~BUZ_PIN)
#define BUZ_OFF()    GPIOPinWrite(GPIO_PORTB_BASE, BUZ_PIN, BUZ_PIN)  

#define SPEED_PIN1   GPIO_PIN_3
#define SPEED_PIN2   GPIO_PIN_4

#define SPEED_NUM_MAX  30

long   SpeedCnt=0;                     //转速计数器
long   ExpSpeed=3000;                  //期望转速,分/转
long   CurDuty=DutyBase;               //当前占空比
uint8  TsmpCnt=10;                     //采样计数器
uint32 UartTimeout;                    //串口超时计数器
uint32 SpeedNum=1;                     //转速记录数
uint8  DirClockwise=1;                 //转速方向
uint16 CompCnt=0;                      //比较器计数器   
uint8  OverCur=0;                      //过流标志 

uint8 Speed_Queue[SPEED_NUM_MAX*4+20];
uint8 UartData[SPEED_NUM_MAX*4+100];
uint8 Auto_Rec_Speed=0;

long Bytes_To_Long(uint8 *Buffer)      //4个字节合成一个长整型数
{
  long lTemp;

  lTemp=(long) (Buffer[0]+(Buffer[1]<<8)+(Buffer[2]<<16)+((Buffer[3]& 0x7F)<<24));

  if(Buffer[3] & 0x80)
    return( lTemp*(-1) );
  else
    return(lTemp);
}

void Long_To_Bytes(long LongData, uint8 *Buffer) //长整型数分成4个字节
{
  long lTemp;
  
  lTemp=LongData;

  if(lTemp<0)
  { 
    lTemp=lTemp*(-1);
    Buffer[3]=( (uint8)( (lTemp>>24) & 0x7F ) ) | 0x80; 
  }
  else
  {
    Buffer[3]=( (uint8)( (lTemp>>24) & 0x7F ) ); 
  }

  Buffer[0]=(uint8)(  lTemp & 0xFF );
  Buffer[1]=(uint8)( (lTemp>>8) & 0xFF );
  Buffer[2]=(uint8)( (lTemp>>16) & 0xFF );
}

void Delay(uint32 n)                   //延时函数
{
  while(n--);
}

/****************************GPIO*****************************/
/*************************************************************/
void GPIOInit(uint8 PA_Prio)
{
   //设置LED1、LED2、蜂鸣器设置为输出
  GPIODirModeSet(GPIO_PORTB_BASE, LED_PIN1 | LED_PIN2 | BUZ_PIN, GPIO_DIR_MODE_OUT);
        
  //设置中断
  IntEnable(INT_GPIOA);
  IntPrioritySet(INT_GPIOA, PA_Prio);
  GPIODirModeSet(GPIO_PORTA_BASE, SPEED_PIN1 | SPEED_PIN2, GPIO_DIR_MODE_IN);
  GPIOIntTypeSet(GPIO_PORTA_BASE, SPEED_PIN1 | SPEED_PIN2, GPIO_FALLING_EDGE);  
  GPIOPinIntEnable(GPIO_PORTA_BASE, SPEED_PIN1 | SPEED_PIN2);
}

void GPIO_Port_A_ISR(void)
{
  static uint8 DirStep=0;
  static uint16 Dir_T1;
  static uint16 Dir_T2;
  
  if( !GPIOPinRead(GPIO_PORTA_BASE, SPEED_PIN1) ) //SPEED1低电平,转速计数器加一
  { SpeedCnt++; }

  switch(DirStep)
  {
    case 0:                            //第0步
      if( !GPIOPinRead(GPIO_PORTA_BASE, SPEED_PIN1) ) //SPEED1低电平
      { 
        TimerLoadSet(TIMER0_BASE, TIMER_B, 0xFFFF);   //复位定时器0B
        DirStep++;                     //下一步
      }
      break;

    case 1:                            //第1步
      if( !GPIOPinRead(GPIO_PORTA_BASE, SPEED_PIN2) ) //SPEED2低电平
      { 
        //读出第一个SPEED1下降沿和SPEED2下降沿之间的时间
        Dir_T1=(uint16)TimerValueGet(TIMER0_BASE, TIMER_B);
        TimerLoadSet(TIMER0_BASE, TIMER_B, 0xFFFF); 
        DirStep++; 
      }
      break;

    case 2:                            //第2步
      if( !GPIOPinRead(GPIO_PORTA_BASE, SPEED_PIN1) ) //SPEED1低电平
      { 
        //读出SPEED2下降沿和第二个SPEED1下降沿之间的时间
        Dir_T2=(uint16)TimerValueGet(TIMER0_BASE, TIMER_B);
        DirStep=0;
        if(Dir_T1>Dir_T2)
        { DirClockwise=1; }            //电机正转中
        else
        { DirClockwise=0; }            //电机反转中
      }
      break;

    default:
      DirStep=0;
      break;
  }                                    //switch
   
  GPIOPinIntClear(GPIO_PORTA_BASE, SPEED_PIN1 | SPEED_PIN2);
}

/************************PWMA & Timer0B************************/
/*************************************************************/
void InitPwmTmr(uint16 CycleNum, uint16 DutyNum)
{
  //PB0为PWM输出
  GPIOPinTypeTimer(GPIO_PORTB_BASE, GPIO_PIN_0); 
   
  //定时器0A产生PWMA,定时器0B为16位计时器
  TimerConfigure(TIMER0_BASE, TIMER_CFG_16_BIT_PAIR | TIMER_CFG_A_PWM | TIMER_CFG_B_PERIODIC);

  ///PWMA的占空比为低电平有效
  TimerControlLevel(TIMER0_BASE, TIMER_A, false);

  //设定周期
  TimerLoadSet(TIMER0_BASE, TIMER_A, CycleNum); 
  
  ///设定占空比
  TimerMatchSet(TIMER0_BASE, TIMER_A, DutyNum);
  
  //定时器0B使用6倍分频
  TimerPrescaleSet(TIMER0_BASE, TIMER_B, 6);

  //使能定时器0A和0B
  TimerEnable(TIMER0_BASE, TIMER_BOTH);
}

#define AdjDutyA(DutyA)  TimerMatchSet(TIMER0_BASE, TIMER_A, DutyA)

/****************************Timer1***************************/
/*************************************************************/
void Timer1Init(uint8 Prio)
{
  //定时器1为32位
  TimerConfigure(TIMER1_BASE, TIMER_CFG_32_BIT_PER);

  //设定超时中断时间
  TimerLoadSet(TIMER1_BASE, TIMER_A, (uint32)(Tsmp*Ftmr1));

  //使能定时器1系统中断
  IntEnable(INT_TIMER1A);

  //设定优先极
  IntPrioritySet(INT_TIMER1A, Prio);

  //使能定时器1中断
  TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);

  //使能定时器1
  TimerEnable(TIMER1_BASE, TIMER_A);
}

void Timer1A_ISR(void)
{
  static uint8 TickCnt=0;
  long lTemp;
  uint8 Buf[10];

  if(CompCnt<100)                      //比较器延时计数器加一
  { CompCnt++; }

  TickCnt++;                           //PID计时器加一
  if(TickCnt<TsmpCnt)                  //时间未到,清除中断标志,退出中断    
  { TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT); return; }
  TickCnt=0;         
  
  lTemp=(long) ( SpeedCnt * ((60/Tsmp)/(TsmpCnt*4 )) ); //计算转速大小 
  if(!DirClockwise)                    //设定转速正负号
  { lTemp=lTemp*(-1); }
  SpeedCnt=0;
   
  if( Auto_Rec_Speed )                 //要求记录转速
  {
    Long_To_Bytes(lTemp, Buf);         //把long型的转速拆成4个byte
    QueueWriteN(Speed_Queue, Buf, 4);  //转速入队列
  }
   
  lTemp = ExpSpeed-lTemp;              //转速误差
 
  lTemp = CurDuty + PID_DltDuty(lTemp); //调用PID函数算出当前PWM的占空比
     
  if(CurDuty != lTemp)
  { 
    CurDuty=lTemp;
     
    if(CurDuty>=PWM_Cycle)             //占空比的时间大于周期
    { CurDuty=PWM_Cycle-1; }
    else if(CurDuty<=0)                //占空比小于零
    { CurDuty=1; }
   
    AdjDutyA( (uint16) CurDuty ); 
  }
   
  UartTimeout++;                       //串口超时计数器加一
 
  TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
}

/*************************Comparator***************************/
/*************************************************************/
void CompInit(uint8 Prio)
{
  //使能比较器0
  SysCtlPeripheralEnable(SYSCTL_PERIPH_COMP0);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

  //P04为C0-输入端
  GPIOPinTypeComparator(GPIO_PORTB_BASE, GPIO_PIN_4);

  //0.825V伏参考电压
  ComparatorRefSet(COMP_BASE, COMP_REF_0_825V);
  
  //低电平触发
  ComparatorConfigure(COMP_BASE, 0, COMP_INT_BOTH | COMP_ASRCP_REF);

  //设置中断优先级
  IntPrioritySet(INT_COMP0, Prio);

  //使能中断
  IntEnable(INT_COMP0);
  ComparatorIntEnable(COMP_BASE, 0);
}

void Analog_Comparator_0_ISR(void)
{
   ComparatorIntClear(COMP_BASE, 0);
   
   if(CompCnt>=100)
   {
      if( !ComparatorValueGet(COMP_BASE, 0) )
      { OverCur=1; }
      else
      { OverCur=0; }
  } 
}


int main(void)
{
  uint8 UartCmd;
  uint16 UartDataLen;
  long i;
  
  Delay(0xF000);                       //复位延时

                                       //使用6MHz时钟源
  SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                 SYSCTL_XTAL_6MHZ);

  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
  
  IntMasterEnable();                   //使能全局中断
 
  Uart0Init(115200, 1<<5) ;            //初始化串口0
  GPIOInit(2<<5);                      //初始化GPIO
  Timer1Init(3<<5);                    //初始化定时器1  
  InitPwmTmr(PWM_Cycle, (uint16)CurDuty); //初始化定时器0
  CompInit(4<<5);                      //初始化比较器0

  LED2_OFF();
  BUZ_OFF();
   
  QueueCreate(Speed_Queue,             //初始化转速队列                        
              SPEED_NUM_MAX*4+20,
              0,
              0);

  while(1)
  {
    if(Uart_DcMt_Rec(Uart0_Rec_Queue, 
                     UartData,
                     &UartDataLen, 
                     &UartTimeout,
                     20)==UART_OK)     //接收到上位机的命令帧
    {
      UartCmd=UartData[0];             //提出命令字节
      
      switch(UartCmd)
      {   
        case UART_CMD_SET_PID:         //设定PID参数命令
          i=(long)(UartData[1]+(UartData[2]<<8)+(UartData[3]<<16)+((UartData[4]& 0x7F)<<24));
          TsmpCnt=(uint8)(i/(Tsmp*1000));   
        
          Ka_PC=Bytes_To_Long(UartData+5);  
          Kb_PC=Bytes_To_Long(UartData+9);  
          Kc_PC=Bytes_To_Long(UartData+13);  
                    
          Uart_DcMt_Send(&UartCmd,1);
          break;
         
        case UART_CMD_SET_SPEED:       //设定转速命令
          ExpSpeed=Bytes_To_Long(UartData+1);
          Uart_DcMt_Send(&UartCmd,1);
          break;
       
        case UART_CMD_GET_RECORD:      //记录转速
          SpeedNum = Bytes_To_Long(UartData+1);
          if(SpeedNum>SPEED_NUM_MAX)
          { SpeedNum=SPEED_NUM_MAX; }
          QueueFlush(Speed_Queue);

          Auto_Rec_Speed=1; 
          while( QueueNData(Speed_Queue) < (SpeedNum*4) );  
          Auto_Rec_Speed=0; 

          UartData[0]=UART_CMD_GET_RECORD;
          i=TsmpCnt*10;
          Long_To_Bytes(i, UartData+1);
          i=SpeedNum;
          Long_To_Bytes(i, UartData+5);
                  
          for(i=0; i<(SpeedNum*4); i++)
          { QueueRead(UartData+9+i, Speed_Queue); }

          Uart_DcMt_Send(UartData, SpeedNum*4+9);
          break;

        case UART_CMD_AUTO_RECORD:     //自动记录转速
          SpeedNum = Bytes_To_Long(UartData+1);
          if(SpeedNum>SPEED_NUM_MAX)
          { SpeedNum=SPEED_NUM_MAX; }
          QueueFlush(Speed_Queue);
          Auto_Rec_Speed=1;
          Uart_DcMt_Send(&UartCmd,1);
          break;
        
        case UART_CMD_STOP_RECORD:     //停止记录转速
          Auto_Rec_Speed=0;
          QueueFlush(Speed_Queue);
          Uart_DcMt_Send(&UartCmd,1);
          break;
     }                                 //switch
     
    }                                  //if

    if( Auto_Rec_Speed && (QueueNData(Speed_Queue) >= (SpeedNum*4)) )
    {
      UartData[0]=UART_RES_SPEED;
      for(i=1; i<=(SpeedNum*4); i++)
      { QueueRead(UartData+i, Speed_Queue); }
      Uart_DcMt_Send(UartData, SpeedNum*4+1);
    }
    
    if(OverCur)
    {
      BUZ_ON();
      LED2_ON();
    }
    else
    {
      BUZ_OFF();
      LED2_OFF();
    }
  }                                    //while(1)

  return(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -