📄 main.c
字号:
#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 + -