Thông báo

Collapse
No announcement yet.

SPI: Master nhận dữ liệu twf slave

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • SPI: Master nhận dữ liệu twf slave

    Mình đag viết chương trình giao tiếp SPI giữa atmega32 và một cảm biến. Chương trình khi biên dịch thì ngon, ngoại trừ cái warning khi biên dịch code của slave:
    main.c:38: warning: statement with no effect
    dòng 38 trong code minh là : "SPI_SlaveInit;"
    Mình loay hoay vs cái code này suôt, với lại cũng mang lên avrfreaks để hỏi mà các cao thủ trên đấy cũng ko chữa dc. các bác xem giúp với.
    ban đầu mình không muốn dùng ngắt của slave nên để code thế này:
    cho master:
    Code:
    /For Master 
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdio.h>
    #include "myLCD.h"
    
    
    #define cbi(port, bit) 	   (port) &= ~(1 << (bit))
    #define sbi(port, bit) 	   (port) |=  (1 << (bit))
    
    //difine SPI pins
    #define SPI_PORT	PORTB
    #define SPI_DDR		DDRB
    #define	SCK_PIN		7
    #define	MISO_PIN	6
    #define	MOSI_PIN	5
    #define Slave		4
    	
    #define ADDRESS_PORT	PORTB
    #define ADDRESS_DDR		DDRB
    
    //initiate SPI in Master mode
    void SPI_MasterInit(void){
            SPI_DDR |=(1<<SCK_PIN)|(1<<MOSI_PIN);
    		SPI_PORT|=(1<<MISO_PIN); //Pull up resister for MISO pin 			
    		//define SS pin for slave
    		ADDRESS_DDR |=(1<<Slave);
    		ADDRESS_PORT|=(1<<Slave);
            SPCR=(1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0); 
    		//SPE: enable, MSTR: Master mode, CPHA: Phase, SPR1:0: prescaler=128		
    }
    
    //Send data, 1 byte, 
    uint8_t SPI_Transmit(uint8_t data){
    		cbi(ADDRESS_PORT, Slave);
            SPDR=data;
            while (bit_is_clear(SPSR,SPIF)); //wait until SPIF is set
    		sbi(ADDRESS_PORT, Slave);
    		return SPDR;
    		
    }
    
    //find length of string
    char len(char s[])
    {
        int x=0;
        while (s[x]!='\0')
            x++;
        return x;
    }
    
    
    //display angle position
    void disp(uint16_t data){
    	uint16_t pos;
    	uint16_t a,b;
    	char disa[3],disb[2];
    	
    	if (data<50)
    		pos=data*141;
    	else
    		pos=data*141+45;
    
    	a=pos/100;
    	sprintf(disa,"%i",a);
    	move_LCD(1,8);
    	print_LCD("   ");
    	move_LCD(1,11-len(disa));
    	print_LCD(disa);
    				
    	b=pos-a*100;
    	sprintf(disb,"%i",b);
    	move_LCD(1,12);
    	if (len(disb)==1){
    		putchar_LCD('0');
    		move_LCD(1,13);
    	}
    	print_LCD(disb);
    		
    	_delay_ms(1);
    	
    }
    
    uint8_t angle;
    
    int main(void){
    
    	
    	init_LCD(); 
    	clr_LCD();
    	
    	print_LCD("vi tri:");
    	move_LCD(1,11);
    	putchar_LCD('.');
    	move_LCD(1,15);
    	putchar_LCD('d');
    
    	SPI_MasterInit(); //initiate SPI
    	_delay_ms(100);	  //wait for slave ready
    
    	while(1){
    	angle=SPI_Transmit(0xFF);//send dummy data
    	disp(angle);//display angle
    	}	
    	return 0;
    }
    cho slave:
    Code:
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    
    //difine SPI pins
    #define SPI_PORT	PORTB
    #define SPI_DDR		DDRB
    #define	SCK_PIN		7
    #define	MISO_PIN	6
    #define	MOSI_PIN	5
    #define	SS_PIN		4
    
    
    //read adc value
    uint8_t read_adc(unsigned char adc_channel){//chuong trinh con doc ADC theo tung channel	
        ADMUX|=adc_channel;
        ADCSRA|=(1<<ADSC); 					//bat dau chuyen doi             
    	loop_until_bit_is_set(ADCSRA,ADIF); //cho den khi nao bit ADIF==1  
        return ADCH;
    }
    
    //initiate SPI in Slave mode
    void SPI_SlaveInit(void){        //18
    		SPI_DDR |=(1<<MISO_PIN);
    		SPI_PORT|=(1<<MOSI_PIN)|(1<<SS_PIN); //Pull up resister for MISO pin 	
    		SPCR=(1<<SPE)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0);
    		//SPE: enable, MSTR=0: Slave mode, CPHA: Phase, SPR1:0: prescaler=128 
    }
    
    uint8_t 	adc_val;
    
    int main(void){	 //26
    	
    	ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS0); 	//enable 8-bit ADC, interrupt not use
    	ADMUX=(1<<ADLAR); 
    	
    	SPI_SlaveInit;
    	
    	while(1){
    		adc_val=read_adc(0);
    		SPDR=adc_val;
    	}
    	return 0;
    }
    sau thì mình dùng ngắt coi như là để slave nhận command từ master trước khi gửi dữ liệu:
    Cho master:
    Code:
    //For Master 
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdio.h>
    #include "myLCD.h"
    
    #define cbi(port, bit) 	   (port) &= ~(1 << (bit))
    #define sbi(port, bit) 	   (port) |=  (1 << (bit))
    
    //difine SPI pins
    #define SPI_PORT	PORTB
    #define SPI_DDR		DDRB
    #define	SCK_PIN		7
    #define	MISO_PIN	6
    #define	MOSI_PIN	5
    #define Slave		4
    	
    #define ADDRESS_PORT	PORTB
    #define ADDRESS_DDR		DDRB
    
    //initiate SPI in Master mode
    void SPI_MasterInit(void){
            SPI_DDR |=(1<<SCK_PIN)|(1<<MOSI_PIN);
    		SPI_PORT|=(1<<MISO_PIN); //Pull up resister for MISO pin 			
    		//define SS pin for slave
    		ADDRESS_DDR |=(1<<Slave);
    		ADDRESS_PORT|=(1<<Slave);
            SPCR=(1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0); 
    		//SPE: enable, MSTR: Master mode, CPHA: Phase, SPR1:0: prescaler=128		
    }
    
    //Send data, 1 byte, 
    uint8_t SPI_Transmit(uint8_t data){
    		cbi(ADDRESS_PORT, Slave);
            SPDR=data;
            while (bit_is_clear(SPSR,SPIF)); //wait until SPIF is set
    		sbi(ADDRESS_PORT, Slave);
    		return SPDR;
    		
    }
    
    //find length of string
    char len(char s[])
    {
        int x=0;
        while (s[x]!='\0')
            x++;
        return x;
    }
    //display angle position
    void disp(uint16_t data){
    	uint16_t pos;
    	uint16_t a,b;
    	char disa[3],disb[2];
    	
    	if (data<50)
    		pos=data*141;
    	else
    		pos=data*141+45;
    
    	a=pos/100;
    	sprintf(disa,"%i",a);
    	move_LCD(1,8);
    	print_LCD("   ");
    	move_LCD(1,11-len(disa));
    	print_LCD(disa);
    				
    	b=pos-a*100;
    	sprintf(disb,"%i",b);
    	move_LCD(1,12);
    	if (len(disb)==1){
    		putchar_LCD('0');
    		move_LCD(1,13);
    	}
    	print_LCD(disb);
    		
    	_delay_ms(1);
    	
    }
    uint8_t angle;
    int main(void){
    	init_LCD(); 
    	clr_LCD();
    	
    	print_LCD("vi tri:");
    	move_LCD(1,11);
    	putchar_LCD('.');
    	move_LCD(1,15);
    	putchar_LCD('d');
    
    	SPI_MasterInit(); //initiate SPI
    	_delay_ms(100);	  //wait for slave ready
    
    	while(1){
    	angle=SPI_Transmit(0xFF);//send dummy data
    	_delay_ms(1);//wait for slave updating data
    	angle=SPI_Transmit(0xFF);//send dummy data
    	disp(angle);//display angle
    	}	
    	return 0;
    }
    cho slave
    Code:
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    //difine SPI pins
    #define SPI_PORT	PORTB
    #define SPI_DDR		DDRB
    #define	SCK_PIN		7
    #define	MISO_PIN	6
    #define	MOSI_PIN	5
    #define	SS_PIN		4
    
    
    //read adc value
    uint8_t read_adc(unsigned char adc_channel){//chuong trinh con doc ADC theo tung channel	
        ADMUX|=adc_channel;
        ADCSRA|=(1<<ADSC); 					//bat dau chuyen doi             
    	loop_until_bit_is_set(ADCSRA,ADIF); //cho den khi nao bit ADIF==1  
        return ADCH;
    }
    
    //initiate SPI in Slave mode
    void SPI_SlaveInit(void){        //18
    		SPI_DDR |=(1<<MISO_PIN);
    		SPI_PORT|=(1<<MOSI_PIN)|(1<<SS_PIN); //Pull up resister for MISO pin 	
    		SPCR=(1<<SPIE)|(1<<SPE)|(1<<CPHA)|(1<<SPR1)|(1<<SPR0);
    		//SPE: enable, MSTR=0: Slave mode, CPHA: Phase, SPR1:0: prescaler=128 
    }
    
    uint8_t 	adc_val;
    
    int main(void){	 //26
    	
    	ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS0); 	//enable 8-bit ADC, interrupt not use
    	ADMUX=(1<<ADLAR); 
    	
    	SPI_SlaveInit;
    	sei();
    	while(1){
    		adc_val=read_adc(0);
    	}
    	return 0;
    }
    ISR(SPI_STC_vect){
    
    SPDR=adc_val;
    }
    Thanks các bác nhiều
    Đây là toàn bộ project của mình bao gồm cả file mô phỏng trên proteus
    SPI-LCD.zip

Về tác giả

Collapse

anhnpson Tìm hiểu thêm về anhnpson

Bài viết mới nhất

Collapse

Đang tải...
X