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:
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:
cho slave:
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:
cho slave
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
main.c:38: warning: statement with no effect
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; }
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; }
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; }
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; }
Đây là toàn bộ project của mình bao gồm cả file mô phỏng trên proteus
SPI-LCD.zip