📄 coder._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 OUTH PD|=0x80
#define OUTL PD&=~0x80
#define LOW_TIME 400
#define SWH_time 900
#define SWL_time 100
Uint ch_time[9]={200,200,200,200,200,200,200,200,200,};//输出用
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 + -