Цитата
Практически такие вещи на "чистом" С не напишешь
Как раз для камней типа AVR пишется на раз. Необходимые средства в штатной сишной библиотеке есть.
Код
#include <setjmp.h>
jmp_buf main_task;
jmp_buf rs_task;
char rs_rstack[8];
char rs_cstack[64];
__interrupt void CNTX_SWT(void)
{
if (!setjmp(main_task)) //Запомнили контекст осн. задачи
{
longjmp(rs_task,1); //Перешли в контекст RS_TRX
}
}
#pragma vector=USART0_RXC_vect
__interrupt __raw void rs_rx(void)
{
((void(*)(void))CNTX_SWT)();
}
#pragma vector=USART0_UDRE_vect
__interrupt __raw void rs_tx(void)
{
((void(*)(void))CNTX_SWT)();
}
#pragma vector=USART0_TXC_vect
__interrupt __raw void rs_txc(void)
{
((void(*)(void))CNTX_SWT)();
}
#pragma vector=TIMER1_OVF_vect
__interrupt __raw void rs_timeout(void)
{
((void(*)(void))CNTX_SWT)();
}
void wait_int()
{
if (!setjmp(rs_task)) //Запомнили контекст RS_TASK
{
longjmp(main_task,1); //Перешли в контекст осн. задачи
}
}
__task __noreturn RS_TRX(void)
{
//Ну, например, вечное эхо
for(;;)
{
char c;
UCSR0B_RXCIE0=1; //Разрешили прерывания от приемника
wait_int();
c=UDR;
UDR=c;
UCSR0B_TXCIE0=1; //Разрешаем прерывания от передатчика
wait_int(); //Ждемс
}
}
void InitRS(void)
{
__disable_interrupt();
((unsigned int *)rs_task)[10]=((unsigned int)rs_rstack)+7; //SP
((unsigned int *)rs_task)[8]=((unsigned int)rs_cstack)+64; //Y
((unsigned int *)rs_task)[9]=(unsigned int)RS_TRX; //Адрес перехода
if (!setjmp(main_task)) longjmp(rs_task,1); //Переходим в RS_TRX
__enable_interrupt();
}
Тут будет выполнен запуск фоновой задачи RS_TRX, которая будет ждать символа из уарта и отправлять его обратно, ждать готовности передатчика и по кругу.
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин