прежде всего ваш код будет иметь ошибку компиляции ! потому что вы не предоставляете ссылку на spi_send_data
функцию
, но давайте представим, что вы включили ее над этой частью кода
проанализируйте свой код
вы говорите, что
выполняется прерывание, программа не возвращается к основному
путь выполнения программы обязательно обратится к основной подпрограмме ... где она go?! :) код выполнит функцию portc_led
один раз ( и только один раз ), может быть, до прерывания или, может быть, после прерывания, или, может быть, прерывание произойдет между функцией ... так что, возможно, portc_led
alredy выполнено происходит до прерывания, но вы не видели его, потому что он был выполнен только за 400 ms
!! и после фин sh прерывания нечего делать просто ждать другого прерывания! ..
простое решение: попробуйте изменить 100ms
задержку в portc_led
на большую задержку, и вы увидите ...
маленькие советы для улучшения практики методы
- посмотрите на этот код
PORTB=(0<<5)
эквивалент portB=0b00000000
когда вы пытаетесь очистить один бит в регистре, вы очищаете все биты регистра! что нехорошо ... используйте этот код PORTB&=~(1<<5)
для очистки одного бита, который заставляет bitwaise & между портом c и 0b11101111 изменять только один бит и сохранять другие биты, как - всегда в подпрограмме прерывания make он настолько мал, насколько вы можете ... просто поднимите флаги и обработайте его в основном l oop ... прочитайте больше, как вы должны сделать это небольшой рутиной
- ваша программа доза не имеет миан л oop !! (иногда его называют super l oop) .. это l oop - это просто бесконечность l oop, которая появляется после инициализации вашей системы и запускается снова и снова ... какой-то компилятор добавляет пустую бесконечность l oop в конце основной подпрограммы и другой порции компилятора не добавляйте ... это хорошая практика иметь main l oop в основной подпрограмме, даже если вы ее не используете! Чтобы ваша программа оставалась в живых
измените код
не то, что следующий код не будет запускать гашение параллельно (одновременно), он будет запускать их последовательно ( не одновременно) .. если вы хотите иметь параллельное гашение, используйте прерывание таймера в portc_led
вместо задержки / или используйте RTOS (немного продвинутый topi c)
#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define ACK 0x01
volatile char spi_interupt_flag = 0;
void portd_led(void)
{
// this will blank led in pd7 for 3 sec
for(char i=0;i<6;i++){
PORTD^=(1<<PD7) ; // toggle pd7
_delay_ms(500); // you will see 500 ms blank
}
}
int main(void)
{
DDRB |= (1<<2)|(1<<3)|(1<<5); // SCK, MOSI and SS as outputs
DDRB &= ~(1<<4); // MISO as input
SPCR |= (1<<MSTR); // Set as Master
SPCR |= (1<<SPR0)|(1<<SPR1); // divided clock by 128
SPCR |= (1<<SPIE); // Enable SPI Interrupt
SPCR |= (1<<SPE); // Enable SPI
DDRC= 0xFF ; // set PORT C as output
DDRD = 0xFF ;
sei();
spi_send_data(ACK); // this code will make compile error if you not provide a source for implementation
while(1){
if (spi_interupt_flag)
{
//this code only execute when data received from SPI
portd_led(); //do whatever you want to do for handle it
spi_interupt_flag = 0; //reset the flag again
}
PORTC^=(1<<PC5); //toggle pc5 for ever
_delay_ms(1000); // pc5 will toggle every 1 sec unless ther is interupt
}
}
ISR(SPI_STC_vect)
{
// just set a flag for handle interrupt in main
spi_interupt_flag = 1;
}