|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2008-11-21 11:05:03
|
显示全部楼层
mega8不知道,我没有用过.
干脆给个完整的程序,自己研究吧。
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.3 Professional
Automatic Program Generator
?Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 2007-2-15
Author :
Company :
Comments:
Chip type : ATmega48V
Clock frequency : 8.000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 128
*****************************************************/
#include <mega48.h>
#include <delay.h>
#define SPI_RX_BUFFER_SIZE 6
#define SPI_RX_BUFFER_MASK ( SPI_RX_BUFFER_SIZE - 1 )
#define SPI_TX_BUFFER_SIZE 3
#define SPI_TX_BUFFER_MASK ( SPI_TX_BUFFER_SIZE - 1 )
#define SPI_SET_MASTER SPCR|=(1<<4)
#define SPI_INT_EANBLE SPCR|=(1<<7)
#define SET_SPI_BUS_MODE PORTB.2
#define GET_SPI_BUS_MODE PINB.2
flash unsigned char Tab[]={
0x3F, //0
0x06, //1
0x5B, //2
0x4F, //3
0x66, //4
0x6D, //5
0x7D, //6
0x07, //7
0x7F, //8
0x6F, //9
0x77, //A
0x7C, //B
0x39, //C
0x5E, //D
0x79, //E
0x71 //F
};
bit spi_m;
bit spi_trans_com;
bit spi_sending;
bit blank_state;
bit send_failure;
bit disp_blanking;
unsigned char SPI_RxBuf[SPI_RX_BUFFER_SIZE];
volatile unsigned char SPI_RxHead;
unsigned char SPI_TxBuf[SPI_TX_BUFFER_SIZE];
volatile unsigned char SPI_TxHead;
volatile unsigned char disp_buffer[8];
volatile unsigned char disp_buffer2[4][2];
volatile unsigned char disp_digit;
//TIMER0 initialize - prescale:1024
// WGM: CTC
// desired value: 10mSec
// actual value: 10.112mSec (-1.1%)
void timer0_init(void)
{
TCCR0B = 0x00; //stop
TCNT0 = 0x00; //set count
OCR0A=0x16;
TCCR0A = 0x02;
TCCR0B = 0x05; //start timer
}
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
PORTD=0x00;
PORTB|=0x03;
PORTC.4=1;
PORTC.5=1;
PORTC&=0xF0;
switch(disp_digit)
{
case 7:
{
PORTB.1=0;
}break;
case 6:
{
PORTB.0=0;
}break;
case 5:
{
PORTC.5=0;
}break;
case 4:
{
PORTC.4=0;
}break;
case 3:
{
if(disp_blanking==0||blank_state==0)
PORTC.3=1;
}break;
case 2:
{
if(disp_blanking==0||blank_state==0)
PORTC.2=1;
}break;
case 1:
{
if(disp_blanking==0||blank_state==0)
PORTC.1=1;
}break;
case 0:
{
if(disp_blanking==0||blank_state==0)
PORTC.0=1;
}break;
default:break;
}
PORTD=disp_buffer[disp_digit];
if(disp_digit<7)
disp_digit++;
else
disp_digit=0;
}
//TIMER1 initialize - prescale:1024
// WGM: 4) CTC, TOP=OCRnA
// desired value: 500mSec
// actual value: 499.968mSec (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
OCR1AH = 0x0A;
OCR1AL = 0x41;
TCCR1A = 0x00;
TCCR1B = 0x0D; //start Timer
}
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
TCCR0B=0x00;
if(blank_state==1)
{
blank_state=0;
disp_buffer[4]=disp_buffer2[0][0];
disp_buffer[5]=disp_buffer2[1][0];
disp_buffer[6]=disp_buffer2[2][0];
disp_buffer[7]=disp_buffer2[3][0];
}
else
{
blank_state=1;
disp_buffer[4]=disp_buffer2[0][1];
disp_buffer[5]=disp_buffer2[1][1];
disp_buffer[6]=disp_buffer2[2][1];
disp_buffer[7]=disp_buffer2[3][1];
}
TCCR0B=0x05; //start timer
}
// Timer 2 output compare interrupt service routine
interrupt [TIM2_COMPA] void timer2_compa_isr(void)
{
// Place your code here
}
//******************************************
// SPI 中断服务程序
//******************************************
interrupt [SPI_STC] void spi_isr(void)
{
unsigned char data;
if(spi_m==0) //如果spi_m为0,表明是接收状态
{
data = SPDR; //读入接受到的数据
SPI_RxBuf[SPI_RxHead-2] = data; //将接收到的数据存入接收缓存区
if ( SPI_RxHead ==( SPI_RX_BUFFER_MASK+2)) //如果是接收帧的最后一个数据
{
if(GET_SPI_BUS_MODE==1)
{
SPI_RxHead = 0; //已接收数据还原
SPI_SET_MASTER; //接收完成,将SPI设回主方式
spi_trans_com=1; //置接收完成标志
}
/*DDRB.2=1;
SET_SPI_BUS_MODE=0; */ //处理数据中,禁止发送方发送
}
else
{
SPI_RxHead++; //已接收数据计数器加1
}
}
else //如果spi_m为1,表明是发送状态
{
if ( SPI_TxHead <= SPI_TX_BUFFER_MASK) //如果要发送的数据还未全部发完
{
SPDR = SPI_TxBuf[SPI_TxHead]; //从发送缓存区取数发送
SPI_TxHead++; //已发送数据计数器加1
}
else //如果要发送的数据已全部发完
{
SPI_TxHead=0; //已发送数据计数器还原
DDRB.2=0;
SET_SPI_BUS_MODE=1; //释放总线,以便接收方进入主发送。
spi_m=0;
spi_sending=0; //清空发送中标记
}
}
}
//******************************************
// SPI 初始化
//******************************************
void InitSPI(void)
{
SPI_RxHead = 0;
SPI_TxHead = 0;
SPCR=0xD2;
// Clear the SPI interrupt flag
#asm
nop
in r30,spsr
in r30,spdr
#endasm
}
//******************************************
//发送数据
//******************************************
void spi_send(void)
{
unsigned char temp;
delay_us(50);
if(spi_sending==0) //发送中标记为0,表明spi发送空闲
{
spi_sending=1; //置spi_sending标志表明发送进行中
SPI_TxBuf[SPI_TX_BUFFER_MASK]=0;
for(temp=0;temp<SPI_TX_BUFFER_MASK;temp++) //计算校验和
{
SPI_TxBuf[SPI_TX_BUFFER_MASK]+=SPI_TxBuf[temp];
}
//fill_tx_buffer(); //调用fill_tx_buffer函数,将要发送的数据加载到发送缓冲区
if(GET_SPI_BUS_MODE==0) //如果PINB.2为低,表明总线被接受方占用,等待直至接受方发送完成。
{
for(temp=0;temp<200;temp++)
{
delay_us(100);
if(GET_SPI_BUS_MODE==1)
{
break;
}
}
}
if(temp<100)
{
InitSPI(); //初始化spi为主方式
DDRB.2=1;
SET_SPI_BUS_MODE=0; //将PORTB.2拉低,强迫接收方进入从接收方式
spi_m=1; //置spi_m标志表明为发送状态
delay_us(10);
SPDR=0xFF; //开始发送
SPI_INT_EANBLE; //开SPI中断,
SPI_TxHead = 0; //已发送数据计数器清0
send_failure=0;
}
else
{
send_failure=1;
spi_sending=0;
}
}
}
//*********************************************************
//设定显示数值
//*********************************************************
void set_disp_vol(void)
{
int data;
unsigned char i;
data=(int)SPI_RxBuf[4]*0x100+SPI_RxBuf[3];
if((data>9999&&SPI_RxBuf[1]==0x00)||(data>999&&SPI_RxBuf[1]==0x01)) // 如果超出显示范围,显示“----“
{
for(i=0;i<4;i++)
disp_buffer=0x40;
}
else
{
for(i=0;i<4;i++)
{
disp_buffer=Tab[data%10]; //查字形表
data/=10;
}
switch(SPI_RxBuf[2]) //消零
{
case 0:
{
for(i=3;i>0;i--)
{
if(disp_buffer==0x3F)
disp_buffer=0;
else
break;
}
} break;
case 1:
{
for(i=3;i>1;i--)
{
if(disp_buffer==0x3F)
disp_buffer=0;
else
break;
}
} break;
case 2:
{
if(disp_buffer[3]==0x3F)
disp_buffer[3]=0;
} break;
default:break;
}
if(SPI_RxBuf[2]>0&&SPI_RxBuf[2]<4)
disp_buffer[SPI_RxBuf[2]]|=0x80; //显示小数点
}
if(SPI_RxBuf[1]==0x01) //显示负号
{
disp_buffer[3]=0x40;
}
}
/*inline send_rx_ok(void)
{
while(spi_sending==1);
SPI_RxBuf[0]=0x00;
SPI_RxBuf[0]=0x00;
spi_send();
} */
void spi_bus_waiting(void)
{
unsigned char temp=0;
while(spi_sending==1)
{
delay_us(10);
temp++;
if(temp>100||spi_sending==0)
{
spi_sending=0;
break;
}
}
}
void read_rx_buffer(void)
{
unsigned char check_sum,temp;
DDRB.2=1;
SET_SPI_BUS_MODE=0; //处理数据中,禁止发送方发送
check_sum=0;
for(temp=0;temp<SPI_RX_BUFFER_MASK;temp++) //计算校验和
{
check_sum+=SPI_RxBuf[temp];
}
if(SPI_RxBuf[SPI_RX_BUFFER_MASK]==check_sum)//校验正确
{
switch (SPI_RxBuf[0])
{
case 0x00://总线传输状态代码
{
if( SPI_RxBuf[1]==0x01) //受到出错代码,重发
{
spi_send();
}
}break;
case 0x10://功能错误代码
{
TCCR0B=0x00;
disp_buffer[3]=0x79; //E
disp_buffer[2]=0x40; //-
disp_buffer[0]=Tab[SPI_RxBuf[1]%10]; //查字形表
SPI_RxBuf[1]/=10;
disp_buffer[1]=Tab[SPI_RxBuf[1]%10];
TCCR0B=0x05;
//send_rx_ok();
}break;
case 0x20://显示数据
{
TCCR0B=0x00;
set_disp_vol();
TCCR0B=0x05;
//send_rx_ok();
}break;
case 0x30://led灯数据
{
//TCCR0B=0x00;
disp_buffer2[0][0]=SPI_RxBuf[4];
disp_buffer2[1][0]=SPI_RxBuf[3];
disp_buffer2[2][0]=SPI_RxBuf[2];
disp_buffer2[3][0]=SPI_RxBuf[1];
//TCCR0B=0x05;
//send_rx_ok();
}break;
case 0x31://led灯数据
{
//TCCR0B=0x00;
disp_buffer2[0][1]=SPI_RxBuf[4];
disp_buffer2[1][1]=SPI_RxBuf[3];
disp_buffer2[2][1]=SPI_RxBuf[2];
disp_buffer2[3][1]=SPI_RxBuf[1];
//TCCR0B=0x05;
//send_rx_ok();
}break;
case 0x40://显示命令
{
if(SPI_RxBuf[1]==0x00) //关闪烁
{
disp_blanking=0;
}
if(SPI_RxBuf[1]==0x01) //闪烁
{
disp_blanking=1;
}
//send_rx_ok();
}break;
case 0x50://显示程序号
{
TCCR0B=0x00;
disp_buffer[3]=0x73; //P
disp_buffer[2]=0x40; //-
disp_buffer[0]=Tab[SPI_RxBuf[1]%10]; //查字形表
SPI_RxBuf[1]/=10;
disp_buffer[1]=Tab[SPI_RxBuf[1]%10];
TCCR0B=0x05;
//send_rx_ok();
}break;
case 0x60://显示文字
{
TCCR0B=0x00;
disp_buffer[3]=SPI_RxBuf[4];
disp_buffer[2]=SPI_RxBuf[3];
disp_buffer[1]=SPI_RxBuf[2];
disp_buffer[0]=SPI_RxBuf[1];
TCCR0B=0x05;
//send_rx_ok();
}break;
default:break;
}
}
else //校验失败,发送出错代码
{
spi_bus_waiting();
SPI_TxBuf[0]=0x00;
SPI_TxBuf[1]=0x01;
spi_send();
}
spi_trans_com=0;
DDRB.2=0;
SET_SPI_BUS_MODE=1; //处理完,允许发送方发送
}
void main(void)
{
// Declare your local variables here
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=Out Func4=In Func3=Out Func2=In Func1=Out Func0=Out
// State7=T State6=T State5=0 State4=P State3=0 State2=P State1=0 State0=0
PORTB=0x14;
DDRB=0x2B;
// Port C initialization
// Func6=In Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State6=T State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTC=0x00;
DDRC=0x3F;
// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00;
DDRD=0xFF;
timer0_init();
timer1_init();
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 125.000 kHz
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
TIMSK0=0x02;
TIMSK1=0x02;
TIMSK2=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;
InitSPI();
// Global enable interrupts
#asm("sei")
disp_buffer[0]=0xFF;
disp_buffer[1]=0xFF;
disp_buffer[2]=0xFF;
disp_buffer[3]=0xFF;
disp_buffer[4]=0xFF;
disp_buffer[5]=0xFF;
disp_buffer[6]=0xFF;
disp_buffer[7]=0xFF;
disp_buffer2[0][0]=0xFF;
disp_buffer2[1][0]=0xFF;
disp_buffer2[2][0]=0xFF;
disp_buffer2[3][0]=0xFF;
disp_buffer2[0][1]=0x00;
disp_buffer2[1][1]=0x00;
disp_buffer2[2][1]=0x00;
disp_buffer2[3][1]=0x00;
//disp_blanking=1;
while (1)
{
if(spi_trans_com==1)
read_rx_buffer();
if(send_failure==1)
spi_send();
};
} |
|