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

📄 coder.c

📁 m8改造4VF遥控器
💻 C
字号:
//中断方式发送PWM脉冲,负脉冲,变化范围为1MS~2MS。INT0为教练接口输入负脉冲,INT1为教练接口2,输入正脉冲后自动翻转,
//外部中断接口打开上拉。隔离脉冲为500US
//有一个教练允许开关,打开后进入死循环,并允许外部中断,前提条件是有信号,用定时器0进行信号有无判断
//定时器1采用比较匹配方式触发中断进行信号发送


#include <iom8v.h>
#include <macros.h>

#define Uchar unsigned char
#define Uint unsigned int


#define nop() asm("nop")
#define _nop_() asm("nop")


#define PB PORTB
#define PC PORTC
#define PD PORTD
 
#define IN0 PIND&0x04
#define IN1 PIND&0x08

#define LEDH PB|=0x01
#define LEDL PB&=~0x01

#define BUTTON1 PINB&0x02
#define BUTTON2 PINB&0x04
#define BUTTON3 PINB&0x08
#define BUTTON4 PINB&0x10
#define BUTTON5 PINB&0x20

#define OUTL PD|=0x80
#define OUTH PD&=~0x80

#define LOW_TIME 400
#define SWH_time 900
#define SWL_time 100

Uint ch_time[9]={1000,1000,1000,1000,1000,1000,1000,1000,1000};//输出用
Uint time[9];//输出缓存
Uchar ch_counter=0;//通道计数,用来与数据采集同步
Uchar input=0;//信号输入有无标志
Uchar train=0;//训练开始表示,防止切换时发生抖舵

void port_init(void)
{
 PORTB = 0x3E;
 DDRB  = 0x01;
 PORTC = 0x00; //m103 output only
 DDRC  = 0x00;
 PORTD = 0x0C;
 DDRD  = 0x80;
}

//c输入

//TIMER0 initialize - prescale:1024
// desired value: 1Hz
// actual value: Out of range
void timer0_init(void)
{
 TCCR0 = 0x00; //stop
 TCNT0 = 0x00 /*INVALID SETTING*/; //set count
 //TCCR0 = 0x05; //start timer
}

#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
 input=0;
 train=0;
}

//TIMER1 initialize - prescale:8
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Hz
// actual value: Out of range
void timer1_init(void)
{
 TCCR1B = 0x00; //stop
 TCNT1H = 0x00 /*INVALID SETTING*/; //setup
 TCNT1L = 0x00 /*INVALID SETTING*/;
 OCR1AH = 0x00 /*INVALID SETTING*/;
 OCR1AL = 0x00 /*INVALID SETTING*/;
 OCR1BH = 0x00 /*INVALID SETTING*/;
 OCR1BL = 0x00 /*INVALID SETTING*/;
 ICR1H  = 0x00 /*INVALID SETTING*/;
 ICR1L  = 0x00 /*INVALID SETTING*/;
 TCCR1A = 0x00;
 TCCR1B = 0x02; //start Timer
}

#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
 //compare occured TCNT1=OCR1A//本函数来自4Vf改装系统,有部分改变
 static Uchar output_static=1;//输出状态,0代表即将输出一个低电平,1代表即将输出一个高电平
                           //第一次发信号先发一个低电平
 	
Uchar counter;//普通计数器用来拷贝数据

					   
output_static=!output_static;
  
switch(output_static)
{
case 0:OUTH;
       TCNT1=0;//定时器清零
	   OCR1A=LOW_TIME;
	   if(ch_counter==9)ch_counter=0;//计数清零同步放行
break;

case 1:OUTL;
       TCNT1=0;//定时器清零
	   OCR1A=ch_time[ch_counter];  
	        if(ch_counter==8)//最后一个高电平是同步电平
	   {
	      for(counter=0;counter<=8;counter++)
	      {
	      ch_time[counter]=time[counter]+600;
		  
	      }
	   }
	   ch_counter++;
}// switch(output_static)

}//void timer1_compa_isr(void)



//ADC initialize
// Conversion time: 104uS
void adc_init(void)
{
 ADCSR = 0x00; //disable adc
 ADMUX = 0x00; //select adc input 0
 ACSR  = 0x80;
 ADCSR = 0x86;
}

//Watchdog initialize
// prescale: 32K 
void watchdog_init(void)
{
 WDR(); //this prevents a timout on enabling
 WDTCR = 0x18;
 WDTCR = 0x09; //WATCHDOG ENABLED - dont forget to issue WDRs
 
}



//call this routine to initialize all peripherals
void init_devices(void)
{
 //stop errant interrupts until set up
 CLI(); //disable all interrupts
 
 port_init();
 timer0_init();
 timer1_init();
 adc_init();
 OSCCAL=0xb3;
 watchdog_init();
 MCUCR = 0x05;
 //GICR//中断开关应在MAIN中用开关和信号有无控制
 GICR  = 0x00;
 TIMSK = 0x11; //timer interrupt sources
 SEI(); //re-enable interrupts
 //all peripherals are now initialized
}



#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
 //external interupt on INT0 负输入
 TCNT0 = 0x00 ;//有信号
 input=1;
 if(train)//先不忙发送
 switch(IN0)
 {
 case 0:
 OUTL;
 break;
 case 0x04:
 OUTH;
 }
}

#pragma interrupt_handler int1_isr:3
void int1_isr(void)
{
 //external interupt on INT1 正输入自动反向
 TCNT0 = 0x00 ;//有信号
 input=1;
 if(train)//先不忙发送
  switch(IN1)
 {
 case 0:
 OUTH;
 break;
 case 0x08:
 OUTL;
 }
 
}



void Putchar (Uchar c)
{
while(!(UCSRA&(1<<UDRE)));
UDR=c;
}


Uint ReadADC (Uchar channel)
{
Uint int1,int2;
ADMUX&=~0x1F;
ADMUX|=channel;
ADCSRA|=0x40;
while(~ADCSRA&0x10){}
ADCSRA|=0x10;
int2=ADCL;
int1=ADCH;
int1<<=8;
return (int1+int2);
}


main()
{

Uint batt;//电量
Uint temp[4];//滤波用
Uint youmen ;//油门缓存
Uchar counter ;//采集计数
Uchar safe=1,safedelay=0;//油门保护
Uchar warning_frequency;//警告频率
Uchar warning_counter=0;
Uchar ledonof=0;
Uchar battcheck=1;//检测电量许可
Uchar checken=200;//等待电压稳定

init_devices();


while(1)
{


for(counter=0;counter<=3;counter++)
{
temp[counter]=ReadADC (counter);
if((temp[counter]>time[counter]+1)||(temp[counter]<time[counter]-1))time[counter]=temp[counter];

}

batt=ReadADC (4);

if(BUTTON1)time[4]=SWL_time;else time[4]=SWH_time;
if(BUTTON2)time[5]=SWL_time;else time[5]=SWH_time;
if(BUTTON3)time[6]=SWL_time;else time[6]=SWH_time;
if(BUTTON4)time[7]=SWL_time;else time[7]=SWH_time;

time[8]=12000-time[0]-time[1]-time[2]-time[3]-time[4]-time[5]-time[6]-time[7];

WDR();

if(safe)
{
youmen=time[2];
time[2]=0;
if(safedelay>3)
 {
  if(youmen<50)safe=0;
 }
else safedelay++;
}


if(!(BUTTON5))
{
TCCR0 = 0x05; //start timer//开始判断有无信号
GICR  = 0xC0;//外中断开
  if (input)
  {
  TCCR1B = 0x00;//原来的信号发送关闭
  train=1;//开始训练
  ch_counter=0;//等待放行
  }
  else
  {
  TCCR1B = 0x02;
  train=0;//退出时关闭训练
   ////原来的信号发送打开
  }
}//if(!(BUTTON5))
else
{
GICR  = 0x00;//外中断关
TCCR0 = 0x00;
TCNT0 = 0x00;
train=0;
input=0;
TCCR1B = 0x02;
}

////////////////////////////

if(checken==0)
{
if(battcheck)
{
if(batt<450) //进入报警状态
{
  if(batt>393) //进入频闪状态
{
warning_frequency=batt-390;
warning_counter++;
if(warning_counter>=warning_frequency)
{
warning_counter=0;
ledonof=!ledonof;
if(ledonof)LEDH;
else LEDL;
}
}
 else {LEDH;battcheck=0; }//进入长亮状态,不允许电压回升

}

else LEDL;  //关闭
}
}//if(checken==0)
else checken--;


////////////////////////////

while(ch_counter);

}//while(1)

}

⌨️ 快捷键说明

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