?? speed check avr.c
字號:
//ICC-AVR application builder : 2006-2-24 14:20:32
// Target : M48
// Crystal: 8.0000Mhz
//本程序采用M/T法進行測速,高速時采用M法,低速時采用T法。M1、M2分別為編碼器脈沖計數和時鐘脈沖計數
#include <iom48v.h>
#include <macros.h>
//#include <slavr.h>
#define TLC5615_CS(x) if(x==1)PORTB|=BIT(PB1);else PORTB&=~BIT(PB1)
#define MAX7219_CS(x) if(x==1)PORTB|=BIT(PB2);else PORTB&=~BIT(PB2)
#define SIGB 3//B輸入接Pd3
#define LED_NUM 5//顯示LED的個數為5
#define MAX_5615 811//輸出為10V時5615的值
#define MIN_5615 9 //輸出為-10V時5615的值
#define ZERO_5615 410//輸出為0V時5615的值
#define M_T_Point 16//M/T法的速度分界點,上一次計算得出的速度小于此值,則采取T法計算當前速度,否則采用M法計算
unsigned char led_buff[LED_NUM]={18,0,0,0,0};//led_buffer[0] is direction,other is rev
const unsigned char Driver_table[8]={0x0c,0x01,0x0b,0x04,0x0a,0x0a,0x09,0x00};
const unsigned char seg_table[]={0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b,
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00};
unsigned int Cnt_M1=1,Cnt_M1_Cur=1;//the number of pulse
unsigned int Spd_buff[]={0,0,0,0};//速度顯示緩沖器,用來存儲轉速
unsigned int Cnt_M2=1,Cnt_M2_Cur=1;//number of counter within Cnt_M1
unsigned int N_Last=24;//last rev
unsigned int N_Current=0;//current rev
unsigned char Flag_M1=0x00;//the flag of start counting
unsigned char V_Flag=0;//速度計算方法選擇標志
unsigned int Speed_Num=0;//編碼脈沖計數值,本例中為INTO的脈沖個數
unsigned char Calc_Flag=0;//速度計算標志,需進行計算時為0xff
unsigned char Run_Dir=0;//運行方向,正轉時為0
unsigned char T1_OVF_Cnt=0;//T1溢出次數計數
unsigned char DISP_Cnt=0;//顯示刷新時間控制
unsigned int DA_OUT=0;//DA輸出
void DA_transmit(unsigned int data);
void Refresh(void);
void port_init(void)
{
PORTB = 0x06;
DDRB = 0xFF;//B口為輸出
PORTC = 0x00; //m103 output only
DDRC = 0x00;
PORTD = 0x00;
DDRD = 0x00;//D口為輸入
}
//TIMER1 initialize - prescale:8
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 1Hz
// actual value: Out of range
void timer1_init(void)//用來計算M2值
{
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;
}
//TIMER0 initialize - prescale:1024
// WGM: Normal
// desired value: 20mSec
// actual value: 19.968mSec (0.2%)
void timer0_init(void)
{
TCCR0B = 0x00; //stop
TCNT0 = 0x64; //set count
TCCR0A = 0x00;
TCCR0B = 0x05; //start timer
}
#pragma interrupt_handler timer0_ovf_isr:17
void timer0_ovf_isr(void)
{
SEI();//開中斷,允許中斷嵌套
DISP_Cnt++;
TCNT0 = 0x64; //set count //TIMER0 has overflowed
DA_OUT=N_Current/5;//????????
if(Run_Dir==0)
{
DA_OUT+=ZERO_5615;
}
else
{
DA_OUT=ZERO_5615-DA_OUT;
}
DA_transmit(DA_OUT);
if(DISP_Cnt>=10)//每200MS刷新一次顯示
{
Refresh();
DISP_Cnt=0;
}
}
#pragma interrupt_handler timer1_ovf_isr:14
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
T1_OVF_Cnt++;
N_Last=M_T_Point;
N_Current=M_T_Point; //將這兩個值給0是否可以消除不回零的情況呢?????????
V_Flag=0;//采用T法計算速度
Calc_Flag=0xFF;//計算速度
EIMSK&=~BIT(INT1);//INT1中斷禁止
}
void SPI_transmit(unsigned char data,unsigned char addr)
{
unsigned char temp;
MAX7219_CS(0);
SPDR=addr;
while(!(SPSR&(1<<SPIF)));
SPDR=data;
while(!(SPSR&(1<<SPIF)));
MAX7219_CS(1);
}
//Refresh LED Displayer
void Refresh(void)
{
unsigned char i,temp;
if(Run_Dir==0)
led_buff[0]=18;
else
led_buff[0]=10;
for(i=0;i<LED_NUM;i++)
{
temp=led_buff[i];
temp=seg_table[temp];
SPI_transmit(temp,i+1);
}
}
void init_7219(void)
{
unsigned char cmd_code,led_addr;
int i,j;
for(i=0;i<4;i++)
{
j=i*2;
cmd_code=Driver_table[j+1];
led_addr=Driver_table[j];
SPI_transmit(cmd_code,led_addr);
}
Refresh();
}
//SPI initialize
// clock rate: 125000hz
void spi_init(void)
{
SPCR = 0x52; //setup SPI
SPSR = 0x01; //setup SPI
}
void Rev_transfer(unsigned int rev)//將速度值存儲到顯示緩沖區
{
unsigned char i;
for(i=1;i<5;i++)
{
led_buff[5-i]=rev%10;//依次取個位、十位、百位、千位
rev/=10;
}
}
void Calc_Speed(void)//M/T法公式為N=(60f/p)*(M1/M2)=(60*1M/600)*(M1/M2)=100000*(M1/M2)
{
unsigned long temp=0;
if(V_Flag==0xFF)//M法
{
temp=100000*Cnt_M1;
N_Current=temp/Cnt_M2;
}
else
{
N_Current=25000/Cnt_M2;//T法,此時M1=1/4
}
}
#pragma interrupt_handler int0_isr:2
void int0_isr(void)
{
T1_OVF_Cnt=0;//timer1溢出中斷次數清零
Run_Dir=PIND&(1<<SIGB);//INT0上升沿中斷時,若SIGB=0時為正向
if(V_Flag==0)//speed low,采用T法測速
{
EIFR|=BIT(INTF1);//清INT1中斷標志,防止錯誤中斷
EIMSK|=BIT(INT1);//enable INT1
TCCR1B = 0x00; //stop
TCNT1H = 0x00;
TCNT1L = 0x00;//clear timer1
TCCR1B = 0x02; //start Timer,并且為8分頻
}
else
{
if(Flag_M1==0)//開始用M法測速
{
Flag_M1=0xFF;
TCCR1B = 0x00; //stop
TCNT1H = 0x00;
TCNT1L = 0x00;//clear timer1
TCCR1B = 0x02; //start Timer
Cnt_M1_Cur=N_Last>>3;//M1的值為上次速度的1/8
Speed_Num=0;
}
else
{
Speed_Num++;
if(Speed_Num>=Cnt_M1_Cur)
{
TCCR1B = 0x00; //stop
Calc_Flag=0xFF;
Cnt_M2_Cur=TCNT1L;
Cnt_M2_Cur+=(unsigned int)(TCNT1H<<8);//讀取M2的值
Flag_M1=0;
}
}
}
}
#pragma interrupt_handler int1_isr:3
void int1_isr(void)
{
Calc_Flag=0xFF;//計算速度
TCCR1B = 0x00; //stop timer1
Cnt_M2_Cur=TCNT1L;
Cnt_M2_Cur+=(unsigned int)(TCNT1H<<8);//讀取M2值
EIMSK&=~BIT(INT1);//disable INT1
TCCR1B = 0x02;//enable timer1
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
spi_init();
timer0_init();
timer1_init();
MCUCR = 0x00;
EICRA = 0x07; //extended ext ints,INT0為上升沿中斷,INT1為任意沿中斷
EIMSK = 0x01;//open INT0 interrupt
TIMSK0 = 0x01; //timer 0 溢出中斷使能
TIMSK1 = 0x01; //timer 1 溢出中斷使能
TIMSK2 = 0x00; //timer 2 interrupt sources
PCMSK0 = 0x00; //pin change mask 0
PCMSK1 = 0x00; //pin change mask 1
PCMSK2 = 0x00; //pin change mask 2
PCICR = 0x00; //pin change enable
PRR = 0x00; //power controller
init_7219();
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void DA_transmit(unsigned int data)//將DA數據發送到5615
{
unsigned char temp1,temp2;
data<<=2;//5615為12位數據輸出,最低2位為無效位,所以輸出數據左移兩位
temp1=data>>8;//DA高8位
temp2=data;//DA低8位
TLC5615_CS(0);
SPDR=temp1;
while(!(SPSR&(1<<SPIF)));
SPDR=temp2;
while(!(SPSR&(1<<SPIF)));
TLC5615_CS(1);
}
void main(void)
{
unsigned char i;
unsigned int temp=0;
init_devices();
if(N_Last<M_T_Point)
V_Flag=0;
else
V_Flag=0xff;
while(1)
{
if(Calc_Flag==0xFF)
{
if(T1_OVF_Cnt<1)//T1無溢出
{
Cnt_M1=Cnt_M1_Cur;
Cnt_M2=Cnt_M2_Cur;
Calc_Speed();
}
else//Timer1 溢出
{
N_Current=0;
T1_OVF_Cnt=0;
}
temp=0;
for(i=1;i<4;i++)
{
Spd_buff[4-i]=Spd_buff[3-i];
temp+=Spd_buff[3-i];
}
Spd_buff[0]=N_Current;
temp+=N_Current;
N_Current=temp>>2;//滑動濾波,采用4組數據
N_Last=N_Current;
if(N_Last<M_T_Point)
V_Flag=0;
else
V_Flag=0xff;
Calc_Flag=0;
Rev_transfer(N_Current);
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -