//接收端程序,内部振荡器,8Mhz #include #include #define uint unsigned int #define uchar unsigned char #define h_clk_read DDRD&=~0x08 #define h_clk_ctrl DDRD|= 0x08 #define h_data_read DDRD&=~0x04 #define h_data_ctrl DDRD|= 0x04 #define h_clk_high PORTD|=0x08 #define h_clk_low PORTD&=~0x08 #define h_data_high PORTD|=0x04 #define h_data_low PORTD&=~0x04 //以上定义host端clk与data针脚的输入输出,高低电平 #define CSn_on PORTD|=0x20 #define CSn_off PORTD&=~0x20 #define sclk_on PORTD|=0x80 #define sclk_off PORTD&=~0x80 #define si_on PORTB|=0x01 #define si_off PORTB&=~0x01 #define so_read DDRD&=~0x40 //以上定义CC2500片选和spi针脚各状态 #define burst 0x40 #define read_reg 0x80 #define write_reg 0x00 #define sres 0x30 #define scal 0x33 #define srx 0x34 #define stx 0x35 #define sfrx 0x3a #define sidle 0x36 //以上定义CC2500有关指令 uchar ps2update; uchar tt; uchar sample_rate,resolution,command; uchar frommouse[6]; uchar reply_to_host[4]; void delay(uint tt) {while(tt--);} void timer2_init(void) { TCCR2 = 0x00; //stop ASSR = 0x00; TCNT2 = 0x00; TIMSK = 0x80;//interrupt sourse OCR2 = 50; //interval parameter } #pragma interrupt_handler timer2_comp_isr:4 //设置PS2协议传输的时间间距 void timer2_comp_isr(void) {uchar temp; TCNT2 = 0x00; temp=~PORTD; PORTD|=temp&0x08;PORTD&=temp|0xf7; ps2update++; } uchar sendbyte_to_host(unsigned char bitpointer) //发字节到主机子程序 {uchar i,temp,parity; ps2update=parity=0; h_clk_read;h_clk_high;h_data_read;h_data_high;NOP();NOP(); while(!(PIND&0x08)) { while(!(PIND&0x08))NOP(); delay(50);} h_clk_ctrl;h_data_ctrl;h_data_low;NOP();// send start bit h_clk_low; SEI();TCCR2 = 0x0A; //start,prescale=8,CTC mode while(ps2update!=1);ps2update=0;delay(10); for(i=0;i!=8;i++) {temp=(bitpointer>>i)<<2; if(temp&0x04)parity++; PORTD|=temp&0x04; PORTD&=temp|0xfb; h_clk_read; while(ps2update!=1) { if(!(PIND&0x08)){TCCR2=0x00;CLI();TCNT2=0x00;h_data_high;return 0;} } ps2update=0;h_clk_ctrl; while(ps2update!=1);ps2update=0;delay(10); } if(parity%2==0) h_data_high;//send parity bit else h_data_low; h_clk_read; while(ps2update!=1) { if(!(PIND&0x08)){TCCR2=0x00;CLI();TCNT2=0x00;h_data_high;return 0;} } ps2update=0;h_clk_ctrl; while(ps2update!=1);ps2update=0;delay(10); h_data_high; while(ps2update!=2);ps2update=0;delay(10); // stop bit TCCR2=0x00; CLI();TCNT2 = 0x00; //stop timer h_clk_read;NOP();NOP();//wait for release clock for(i=0;i!=5;i++) {if(!(PIND&0x08))i=0;delay(50);} return 1; } uchar read_command(void) //从主机读命令 {uchar i,temp;uchar return_cmd=0; h_data_read;h_data_high; h_clk_read;h_clk_high;delay(3); for(i=0;i!=51;i++) {while(!(PIND&0x08));//wait for release clock if(PIND&0x04)i=0;//wait for data be low } while(!(PIND&0x08));delay(5); h_clk_ctrl; ps2update=0;temp=0;delay(3); SEI();TCCR2 = 0x0A; //start,prescale=8,CTC mode for(i=0;i!=8;i++) {while(ps2update!=2);ps2update=0;delay(5); temp=PIND&0x04; return_cmd|=(temp>>2)<>(7-i)); PORTB|=temp_SI&0x01; PORTB&=temp_SI|0xfe; PORTD|=0x80; NOP();NOP();NOP(); temp_SO=PIND&0x40; return_SO|=((temp_SO<<1)>>i); NOP();NOP();NOP();NOP();NOP();NOP(); sclk_off; } if((!bitpointer&0x40)) // bitpointer is a cmmd,set CSn & SCLK high {CSn_on;NOP();NOP();NOP(); sclk_on; } return return_SO; } void SPI_host_send(unsigned char bitpointer) //写字节到CC2500,功能兼容SPI_command {uchar i,temp_SI; i=temp_SI=0; sclk_off;NOP();NOP();NOP(); CSn_off;NOP();NOP();//CSn low while(PIND&0x40);delay(3); // wait until SO low for(i=0;i!=8;i++) {NOP();NOP();NOP();NOP();NOP();NOP(); temp_SI=(bitpointer>>(7-i)); PORTB|=temp_SI&0x01; PORTB&=temp_SI|0xfe; sclk_on; NOP();NOP();NOP();NOP();NOP();NOP(); sclk_off; } } uchar SPI_host_read(void) //读字节从CC2500 {uchar i,temp_SO,return_SO; i=temp_SO=return_SO=0; for(i=0;i!=8;i++) { sclk_on;NOP();NOP();NOP(); temp_SO=PIND&0x40; return_SO|=((temp_SO<<1)>>i); NOP();NOP();NOP();NOP();NOP();NOP(); sclk_off; NOP();NOP();NOP();NOP();NOP();NOP(); } return return_SO; } void cc2500_RX_initialization(void) //CC2500初始化 {uchar read; SPI_host_send(sres);delay(1000); SPI_host_send(scal);delay(1000); SPI_host_send(0x00);SPI_host_send(0x07); SPI_host_send(0x06);SPI_host_send(0x06);//fixed packet length =6 SPI_host_send(0x07);SPI_host_send(0x84); SPI_host_send(0x08);SPI_host_send(0x0c); SPI_host_send(0x0b);SPI_host_send(0x09); SPI_host_send(0x0d+burst+write_reg); SPI_host_send(0x5d); SPI_host_send(0xb1); SPI_host_send(0x38); SPI_host_send(0x3d); SPI_host_send(0x3b); SPI_host_send(0x73); SPI_host_send(0xa2); SPI_host_send(0xf8); SPI_host_send(0x01); SPI_host_send(0x07); SPI_host_send(0x30); SPI_host_send(0x18); SPI_host_send(0x1d); SPI_host_send(0x1c); SPI_host_send(0xc7); SPI_host_send(0x00); SPI_host_send(0xb2); CSn_on;NOP();NOP();NOP();NOP();NOP();NOP(); SPI_host_send(0x21);SPI_host_send(0xb6); SPI_host_send(0x23);SPI_host_send(0xca); SPI_host_send(0x26);SPI_host_send(0x11); calibrate: read=SPI_command(sfrx);//sfrx SPI_host_send(scal);delay(690); SPI_host_send(0x25+read_reg);read=SPI_host_read(); while(read==0x3f){SPI_host_send(0x25+read_reg);read=SPI_host_read();} } void main(void) {uchar i,j,readcc2500,buffer; OSCCAL=0xa9; PORTB=0xff;PORTD=0xff; DDRB=0x01;DDRD=0xb0; delay(600); MCUCR = 0x00; GICR = 0x00; TIMSK = 0x00; delay(51000); cc2500_RX_initialization(); timer2_init(); sample_rate=100;resolution=0x03; ps2update=0; finish_init: SPI_command(sfrx); SPI_command(srx); while(9) { SPI_host_send(0xf5);readcc2500=SPI_host_read(); //循环检测CC2500有无接收到数据 if(readcc2500==0x01)//check whether CRC ok { SPI_host_send(0xff); for(tt=0;tt!=6;tt++) {frommouse[tt]=SPI_host_read();} CSn_on;NOP();NOP();NOP();sclk_on;NOP();NOP();NOP(); if((frommouse[0]==0xbb)&&(frommouse[1]==0xaa)) //模拟地址过滤 {for(tt=2;tt!=6;tt++) {to_host: //把无线鼠标的相关字节发回电脑 buffer=sendbyte_to_host(frommouse[tt]); if(buffer==0) {while(!(PIND&0x08)) { while(!(PIND&0x08))NOP(); delay(50);}//每次发字节到主机后都要检测主机有无拉低CLK中止传输 h_data_read;h_data_high;NOP();NOP(); if(!(PIND&0x04))break; else goto to_host; } } } h_data_read;h_data_high;NOP();NOP();NOP(); if(!(PIND&0x04)){SPI_command(sidle);break;} //睡眠CC2500 SPI_command(sfrx); SPI_command(srx); } h_data_read;h_data_high;NOP();NOP();NOP(); if(!(PIND&0x04)){SPI_command(sidle);break;} } command=read_command(); //从主机接收命令并处理 initialization: switch(command) {case 0xff:reply_to_host[0]=0xfa;reply_to_host[1]=0xaa;//reset reply_to_host[2]=0x00;j=3;break;//pass case 0xf6:reply_to_host[0]=0xfa;j=1;break;//set default case 0xf5:reply_to_host[0]=0xfa;j=1;break;//disable report case 0xf2:reply_to_host[0]=0xfa;reply_to_host[1]=0x03;j=2;break;//get ID case 0xea:reply_to_host[0]=0xfa;j=1;break;//set stream mode case 0xe6:reply_to_host[0]=0xfa;j=1;break;//scaling 1:1 case 0xe7:reply_to_host[0]=0xfa;j=1;break;//scaling 2:1 case 0xe9:reply_to_host[0]=0xfa;reply_to_host[1]=0x00;//status request reply_to_host[2]=resolution; reply_to_host[3]=sample_rate;j=4;break; case 0xe8:buffer=sendbyte_to_host(0xfa); //set resolution resolution=read_command();reply_to_host[0]=0xfa;j=1;break; case 0xf3:buffer=sendbyte_to_host(0xfa); //set sample rate sample_rate=read_command();reply_to_host[0]=0xfa;j=1;break; case 0xf4:buffer=sendbyte_to_host(0xfa);goto finish_init; //set resolution } for(i=0;i!=j;i++) {h_clk_read;h_clk_high;h_data_read;h_data_high;delay(3); while(!(PIND&0x08)); if(!(PIND&0x04))break; else buffer=sendbyte_to_host(reply_to_host[i]); } command=read_command(); goto initialization; }