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

📄 main.c

📁 使用IAR编译器开发的ATmega128的程序 有串口通信 IO口控制 定时器 SPI接口等等功能的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "main.h"
#include <iom128.h>
#include <inavr.h>
INT8U RcvData[20];
volatile int RcvOffset=0;//接收缓冲区的偏移
volatile INT8U RcvCmdFlag=0;//已接收一条指令的标志位
volatile INT8U TimerFlag=0;//定时器产生中断的标志位
volatile INT8U VoltageSampleFlag=0;//需要连续采样的标志位
volatile INT8U MotorCtlFlag=0;//0:汽缸静止 1:汽缸前进 2:汽缸后退
volatile INT8U MotorStep=0;//汽缸需要走全程还是半程

void  Timer0Init(void);
void  GPIOInit(void);
void  AD_Init(void);//初始化SPI
void  USART1_Init( INT16U baudrate );
INT8U Decode(INT8U *Src,INT8U SrcLength,INT8U *Dst);
INT8U Encode(INT8U *rcvbuf,INT8U *DstBuf,INT8U length,INT8U *Dstlength);
void USARTCammandPro(INT8U *pCmdBuf,INT8U CmdLength);
void USARTSendCammand(INT8U *pCmdBuf,INT8U CmdLength);
void USARTSendChar(INT8U data);
INT16U AD_Sample(INT8U ADChannel);
INT8U Flag=0;
void main(void)
{
      INT8U   CmdLength=0;
      INT8U   Cmd[20];
      INT32U  TimerIrqCount=0;
      INT8U   QGCount=0;
      INT16U  C12Voltage=0,C13Voltage=0;
      INT32U  MotorDriveFlag=0;
      __disable_interrupt ();
      USART1_Init((INT16U)0x10);//波特率115200
      GPIOInit();//关断所有继电器
      Timer0Init();
      AD_Init();
      __enable_interrupt ();
      while(1)
      {
          if(RcvCmdFlag==(INT8U)1)
          {
              CmdLength=Decode(RcvData,RcvOffset,Cmd);
              if(CmdLength!=(INT8U)0)//命令帧有效
              {  
                USARTCammandPro(Cmd,CmdLength);
              }
              RcvOffset=0;
              RcvCmdFlag=0;
          }
          if(TimerFlag==(INT8U)1)
          {
              if(TimerIrqCount<99999)
                TimerIrqCount++;
              else
                TimerIrqCount=0;
              if(QGCount<7)//汽缸的驱动信号每8秒变换一次电平
                QGCount++;
              else
                QGCount=0;
              if((MotorCtlFlag==(INT8U)1)&&(QGCount==(INT8U)0))//汽缸正向运动
              {
                  MOTORFOWARD
                  MotorDriveFlag++;
                  if((MotorDriveFlag&0x1)==(INT32U)0x01)
                    DRIVEHIGH
                  else
                    DRIVELOW
                  if(MotorDriveFlag>0x9000)//输出若干个方波后 汽缸已到正向的尽头 则停止
                  {
                        if(MotorStep>0)
                        {
                          MotorStep--;
                          MotorDriveFlag=0;
                        }
                        else
                        {
                          MotorCtlFlag=0;
                          MotorDriveFlag=0;
                        }
                  }
                  
              }
              if((MotorCtlFlag==(INT8U)2)&&(QGCount==(INT8U)0))//汽缸反向运动 
              {
                  MOTORBACK
                  MotorDriveFlag++;
                  if((MotorDriveFlag&0x1)==(INT32U)0x01)
                    DRIVEHIGH
                  else
                    DRIVELOW
                  INT8U IOTemp=PINB;                        //对限位开关进行采样,
                  if((IOTemp&0x20)==(INT8U)0x20)//如果限位开关已经关闭(黄线电平为高 红线是电源 黑线是地) 则已经到反向的尽头 则停止
                  {
                      MotorCtlFlag=0;
                      MotorDriveFlag=0;
                  } 
              }
              if((VoltageSampleFlag==(INT8U)1)&&((TimerIrqCount&0x3ff)==(INT32U)0x3ff))//电压采样并反馈
              {
                  INT8U Cmd[5];
                  C12Voltage=0;
                  C13Voltage=0;
                  C12Voltage=AD_Sample((INT8U)6);
                  C12Voltage=AD_Sample((INT8U)6);
                  C13Voltage=AD_Sample((INT8U)7);
                  C13Voltage=AD_Sample((INT8U)7);
                  Cmd[0]=0xe1;
                  Cmd[1]=(INT8U)(C12Voltage>>8);
                  Cmd[2]=(INT8U)C12Voltage;
                  Cmd[3]=(INT8U)(C13Voltage>>8);
                  Cmd[4]=(INT8U)C13Voltage;
                  USARTSendCammand(Cmd,5);      
              }
              else
              TimerFlag=0;
              
          }
      }
}
#pragma vector=TIMER0_COMP_vect
__interrupt  void Timer0_Cmp_Isr(void)//10uS产生一次中断
{
      if(Flag==0)
      {
        Flag=1;
        PORTB &= ~(1<<PORTB0);//PB0可以接一个LED,来判断单片机程序是否跑飞
        DDRB  |= (1<<DDB0);
      }
      else
      {
        Flag=0;
        PORTB |= (1<<PORTB0);
        DDRB  |= (1<<DDB0);
      }
      TimerFlag=1;
      TCNT0=0;
}

#pragma vector=USART1_RXC_vect 
__interrupt void USART1_RX_interrupt( void )
{
      /* Read the received data */
      RcvData[RcvOffset]=(INT8U)UDR1;
      if(RcvData[RcvOffset]==(INT8U)0xff)
        RcvCmdFlag=1;
      if(RcvOffset<19)
        RcvOffset++;
      else
        RcvOffset=0;
}

void  USARTSendChar(INT8U data)
{
      while(!(UCSR1A&(1<<UDRE1)))
        ;
      UDR1=data;
}

void  Timer0Init(void)
{     
      TCCR0  = 0x09;                                      /* Set TIMER0 prescaler to CTC Mode, CLK/256   */
      TCNT0  =    0;                                      /* Start TCNT at 0 for a new cycle             */
      OCR0   = (INT8U)0x7d;
      TIFR  |= 0x02;                                      /* Clear  TIMER0 compare Interrupt Flag        */
      TIMSK |= 0x02;                                      /* Enable TIMER0 compare Interrupt             */
}
void  GPIOInit(void)
{
      PORTB |= (1<<PORTB0);//PB脚为SPI的/SS口 但是当SPI为主机模式时 该脚置成输出不会影响SPI系统
      DDRB  |= (1<<DDB0);
      ALLCLOSE    //所有继电器关闭
      ZEROPOSPINCONF//将检测汽缸位置的引脚置成输入  
}
/* Initialize USART */
void USART1_Init(INT16U baudrate )
{
      /* Set the baud rate */
      UBRR1H = (INT8U) (baudrate>>8);                  
      UBRR1L = (INT8U) baudrate;
      
      UCSR1A |=(1<<U2X1); 
      /* Enable UART receiver and transmitter */
      UCSR1B = ( ( 1 << RXCIE1 ) | ( 1 << RXEN1 ) | ( 1 << TXEN1 ) ); 
      
      /* Set frame format: 8 data 1 stop */
      UCSR1C = (1<<UCSZ11)|(1<<UCSZ10);              //For devices with Extended IO
}
void AD_Init(void)
{     
      DDRB  |= (1 << DDB1)|(1 << DDB2)|(1 << DDB4)|(1<<DDB0);//Set Mosi and SCK output-pin,Set PB4 output to choose ad7888,
                                                             //Set pb0 output in order to avoid spi being slave
      DDRB  &= ~(1 << DDB3);//MOSI为输入
      PORTB |= (1<<PORTB4);///cs is high
      PORTB &= ~( ( 1 << DDB1 ) | ( 1 << DDB2 ) ) ;
      SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0);//|(1<<CPOL)|(1<<CPHA);//enable spi,master,normal mode.MSB First  
}
INT16U AD_Sample(INT8U ADChannel)
{
      INT16U ADC_Result=0;
      INT8U TempHi=0,TempLow=0;
      PORTB &= ~(1<<PORTB4);
      
      SPDR   = ((ADChannel<<3)&0x38)|0x04;
      while(!(SPSR&(1<<SPIF)));
      TempHi=SPDR;//test
      
      SPDR   = ((ADChannel<<3)&0x38)|0x04;
      while(!(SPSR&(1<<SPIF)));
      TempLow=SPDR;
      
      ADC_Result=((TempHi<<8)&0xff00)|TempLow;
      
      PORTB |= (1<<PORTB4);
      
      return ADC_Result;
}
INT8U Decode(INT8U *Src,INT8U SrcLength,INT8U *Dst)
{
      INT8U i=0,j=0;
      INT8U *pcPkt,*pcDstPkt;
      for(i=0;i<SrcLength;)
        if(Src[i]==(INT8U)0xf0)
        {
                j=i;
                break;
        }
        else i++;
      if(i==SrcLength)	//没找到帧头
        return 0;
      for(i=j;i<SrcLength;)
          if(Src[i]==(INT8U)0xff)
          {
                  break;
          }
          else i++;
      if(i==SrcLength)	//没找到帧尾
        return 0;
      INT8U iPktLength=i-j+1;
      pcPkt=&Src[j];
      pcDstPkt=Dst;
      for(i=0,j=0;i<iPktLength;i++)//去掉转义
      {
          if(*pcPkt!=(INT8U)0xf5)
          {
                *pcDstPkt=*pcPkt;
                j++;
                pcDstPkt++;
                pcPkt++;
          }
          else
          {
                pcPkt++;
                i++;//少执行一次循环
                if(*pcPkt==(INT8U)0x00)
                {
                *pcDstPkt=0xf0;
                j++;
                }
                else
                if(*pcPkt==(INT8U)0x0f)
                {
                *pcDstPkt=0xff;
                j++;
                }

⌨️ 快捷键说明

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