Вот пример на Си для Avr Studio
CODE
//Atxmega128A1
//скорость 115200
// тактовая частота 24000000
//bauddivider = 24000000/(8*115200)-1 = 26(dec) - 0x19
#define bauddivider_low 0x19
#define bauddivider_high 0x00
void usartf1_init(void)
{
PORTF_OUTSET=0x80; // удерживаем пин 7 в "1"
// асинхр // паритет выкл// 8 бит
USARTF1_CTRLC=USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc;
// низкое прерывание по окончанию приема и передачи данных
USARTF1_CTRLA=(USARTF1_CTRLA & (~(USART_RXCINTLVL_gm | USART_TXCINTLVL_gm | USART_DREINTLVL_gm))) |
USART_RXCINTLVL_LO_gc | USART_TXCINTLVL_LO_gc | USART_DREINTLVL_OFF_gc;
// скорость 115200
USARTF1_BAUDCTRLA=bauddivider_low;
USARTF1_BAUDCTRLB=bauddivider_high;
// Прием : вкл
// Передача:вкл
// двойная скорость: вкл
// Мульти-процессор: выкл
USARTF1_CTRLB=(USARTF1_CTRLB & (~(USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm | USART_MPCM_bm | USART_TXB8_bm))) |
USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm;
Аналогично конфигурируем остальные USART.
Разрешаем низкие прерывания и "карусельную приоритезацию" (или как там ее) по инглишу вот так называется: Round-robin.// карусель работает только по низким прерываниям.
Код
//конфигурация контроллера прерываний
void PMIC_init(void)
{
unsigned char a;
a=(PMIC_CTRL & (~(PMIC_RREN_bm | PMIC_IVSEL_bm | PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm))) |
PMIC_LOLVLEN_bm | PMIC_RREN_bm;//| PMIC_MEDLVLEN_bm;//| PMIC_HILVLEN_bm;
//CCP=CCP_IOREG_gc;
PMIC_CTRL=a;
PMIC_INTPRI=0x00;
}
нужен еще таймер на 1мсек. Для того что бы установить интервал времени между соседними пакетами.
CODE
// инициализация таймера0
void tcc0_init(void) // таймер на 1 мсек
{
TCC0_CCA=24000000/(1000*2);// частота 1000 Hz
// тактирование DIV 2
TCC0_PER=24000000/(1000*2);// частота 1000 Hz
TCC0_CTRLA=(TCC0_CTRLA & (~TC0_CLKSEL_gm)) | TC_CLKSEL_DIV2_gc;
//режим FRQ/разрешение сравнения в канале А
TCC0_CTRLB=(TCC0_CTRLB & (~(TC0_CCAEN_bm | TC0_CCBEN_bm | TC0_CCCEN_bm | TC0_CCDEN_bm | TC0_WGMODE_gm))) |
TC0_CCAEN_bm | TC_WGMODE_NORMAL_gc;
// разрешение низкого прерывания по сравнению в канале А
TCC0_INTCTRLB=(TCC0_INTCTRLB & (~(TC0_CCDINTLVL_gm | TC0_CCCINTLVL_gm | TC0_CCBINTLVL_gm | TC0_CCAINTLVL_gm))) |
TC_CCDINTLVL_OFF_gc | TC_CCCINTLVL_OFF_gc | TC_CCBINTLVL_OFF_gc | TC_CCAINTLVL_LO_gc;
}
Далее в обработчике прерывания таймера увеличиваем счетчик.
Код
/// обработчики прерываний
ISR(TCC0_CCA_vect) // обработчик прерывания по таймеру 1msec
{
counter_msec++;
}
в основном цикле, сравнивая переменную counter_msec с уставкой, отправляем первый байт пакета. (и сбросить counter_msec не забыть)
В обработчике по окончанию передачи данных нужно отправить следующий байт пакета.
Пример:
CODE
#define RX_BUFFER_SIZE 12 //размер приемного буффера
#define TX_BUFFER_SIZE 41 //размер буффера передачи
#define p RX_BUFFER_SIZE // р - размер окончательного буфера, входящего пакета
#define n p*2+1 // буфер двойной для входящего пакета
// переменные для передачи пакета
char TX_B[41];
unsigned char B_tx_offset; //смещение по пакету
char flag_TX_pack_co;//флаг завершения передачи пакета;
ISR(USARTF1_TXC_vect) //обработчик прерывания по передаче данных
{
if ((B_tx_offset<TX_BUFFER_SIZE)&(flag_TX_pack_complite!=1))
{
USARTF1_DATA = TX_B[++B_tx_offset];
}
if (B_tx_offset==TX_BUFFER_SIZE)
{
B_tx_offset=0;
flag_TX_pack_complite=1;
}
}
И так для всех усартов. Пример обработчика приема данных:
CODE
// переменные для приема пакета char wbuf[n];
//рабочий буфер, где n= удвоенный размер принимаемого пакета + 1 char ebuf[p];
//окончательный буфер, к которому будет обращаться программа, размер = размеру принимаемого пакета char pb, pe;
//индексы в буфере, первый указывает на начало пакета, второй на конец, вначале оба равны нулю
// (пакет в буфере может располагаться не в начале буфера) char flag_RX_pack_co;
// флаг завершения приема пакета unsigned int counter_RX_pack;
// счетчик пакетов
ISR(USARTF1_RXC_vect) //обработчик прерывания по приему данных
{
char x;
wbuf[pe]=USARTF1_DATA; //Пишем принятый символ в массив wbuf[pe]
if((pe-pb)==p) //Если pe - pb равно размеру пакета
{
if((wbuf[pb]==0x0A)&(wbuf[pb+1]==0x20)&(wbuf[pe-1]==0x0D))
//Если wbuf[pb] = стартовому символу И wbuf[pb+1] = индентификатору пакета И wbuf[pe] = стоповому символу
{
for (x=0;x<p;x++)
{
ebuf[x]=wbuf[x+pb];
}
pb=pe=0;
flag_RX_pack_co=1;
counter_RX_pack++;
}
else
{
pb++;
pe++;
}
if(pe==n)
{
pb=pe=0 ;
}
}
else pe++;
}
Разжевал как мог.
Сообщение отредактировал IgorKossak - Apr 12 2012, 06:49
Причина редактирования: длинные строки в [codebox] не переносятся, разбивайте вручную