[an error occurred while processing this directive]
Не знаю, получится ли. Даю пример.
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено Михаил Е. 10 января 2006 г. 17:35
В ответ на: Какие классы обьектов , наследования примерчик плиз отправлено Kenat 10 января 2006 г. 17:21


//***************************************************
//* UART 1 *
//* Связь с платами расширения. *
//***************************************************
class UART1: public Baseclass
{
friend class Input;
public:
UART1();
char * operator & (void); // доступ к массиву OutputBuffer
private:
char mode; // режим - прием фрейма/пауза
bool GetEvent(const Event,unsigned char x=0,void *Tag=0);
void IfChange(); // фоновый процесс
unsigned int CRC16(char*,char); // подсчет контрольной суммы (передача)
char CRC16(void); // подсчет контрольной суммы (прием)
static UART1* UART1Ptr; // указатель на UART
char OutputNum; // счетчик байт на вывод
char *InputPtr; // указатель на буфер приема
char InputByffer[64]; // буфер приема
char OutputBuffer[64]; // массив на передачу
char *OutputPtr; // указатель на буфер передачи
volatile char time; // подсчет времени между пакетами для определения начала фрейма
volatile char flag; // признак принятого фрейма по RS485
volatile char WatchReset; // подсчет циклов для перезапуска WatchDog
//**************** Прием байта **********************
#pragma vector=USART1_RXC_vect
static __interrupt void UART1_RX() // прерывания
{
if(FE1) { if(UDR1); UART1Ptr->mode = 0; return; } // ошибка приема
char x = UDR1; // принять байт
UART1Ptr->time = 3; // отсчет времени между байтами
__enable_interrupt(); // разрешить прерывания
if(!UART1Ptr->mode) // если был режим "пауза"
{
UART1Ptr->mode = 0xff; // режим "прием фрейма"
UART1Ptr->InputPtr = UART1Ptr->InputByffer; // указатель на начало
}
*UART1Ptr->InputPtr++ = x; // положить в буфер
if((UART1Ptr->InputPtr-UART1Ptr->InputByffer)>=sizeof(UART1Ptr->InputByffer))
UART1Ptr->InputPtr--; // указатель вернуть в буфер
}
//*************** Передача байта ********************
#pragma vector=USART1_UDRE_vect
static __interrupt void USART1_UDRE() // прерывания
{
if(!(--UART1Ptr->OutputNum)) // если все байты
{
UDRIE1 = 0; // если все байты, запретить прерывания
TXC1 = 1; // на всяк. случай, иногда были сбои
UDR1 = *(UART1Ptr->OutputPtr++); // передать байт
TXCIE1 = 1; // разрешить прерывания по концу передачи
}
else UDR1 = *(UART1Ptr->OutputPtr++); // передать байт
}
//************ Завершение передачи ******************
#pragma vector=USART1_TXC_vect
static __interrupt void USART1_TXC() // прерывания
{
TXCIE1 = 0; // конец передачи, запретить прерывания
Dir485_2 = INP; // RS485 на прием
UART1Ptr->InputPtr = UART1Ptr->InputByffer; // указатель буфера на начало
RXEN1 = 1; // разрешен прием
if(UDR1); // 1-й байт для чтения может быть сбойным
RXCIE1 = 1; // разрешены прерывания от приемника UART 1
}
};
//************** Конструктор ************************
UART1::UART1()
{
UART1Ptr = this; // Указатель на UART
PORTD |= 4; // подтяжка на RXD включена
DDRD |= 0x10; // управление направлением RS485 - выход
Dir485_2 = INP; // RS485 на прием
flag = time = 0; // отсчет времени между байтами - исходное
InputPtr = InputByffer; // Указатель на начало
OutputPtr = OutputBuffer; // Указатель на начало
OutputNum = 0; // счетчик байт = 0
mode = 0; // режим "пауза" между фреймами
UPM1 = 0; // нет контроля четности
USBS1 = 0; // 1 стоп-бит
UCSZ12 = 0; UCSZ11 = UCSZ10 = 1; // длина 8 бит
U2X1 = 0; UBRR1H = 0; UBRR1L = 25; // скорость 38400
RXEN1 = 1; // разрешен прием
if(UDR1); // первый байт может быть сбойным
RXCIE1 = 1; // разрешены прерывания от приемника UART 1
TXEN1 = 1; // разрешена передача UART 1
WatchReset = 200; // подсчет циклов для перезапуска WatchDog
}
//******* Доступ к массиву OutputBuffer *************
char * UART1::operator & (void)
{
return OutputBuffer; // адрес массива
}
//********** Обработка событий **********************
bool UART1::GetEvent(Event n,unsigned char x,void *Ptr)
{
switch (n)
{
case Time_1s:
case Time_1ms:
if((Dir485_2==INP)&&WatchReset) // если RS485 - прием
WatchReset--; // разрешаем счет для WatchDog
if(time)
{
time--;
if(!time) // последний отсчет после приема фрейма
{
mode = 0; // режим "пауза"
flag = 1; // признак принятого фрейма по RS485
}
}
break; // продолжать обработку
case WriteUART1: // передать массив по UART 1
if(TXCIE1||UDRIE1) return StopEvent; // не закончена предыдущая передача
RXEN1 = 0; // запрешен прием UART 1
RXCIE1 = 0; // запрешены прерывания от приемника UART 1
Dir485_2 = OUT; // RS485 на передачу
int16 CRC; // для вычисления контр. суммы
OutputPtr = OutputBuffer; // указатель на начало OutputBuffer
CRC.Int16 = CRC16(OutputPtr,x); // взять контрольную сумму
OutputBuffer[x++] = CRC.byte[0]; // дописать контрольную
OutputBuffer[x++] = CRC.byte[1]; // сумму к массиву
OutputNum = x-1; // кол-во байт на передачу
UDR1 = *OutputPtr++; // 1-й байт передать
UDRIE1 = 1; // разрешить прерывания от передатчика UART 1
return StopEvent; // конец обработки
}
return ContinueEvent; // продолжать обработку
}
//**************** Фоновая обработка ****************
void UART1::IfChange()
{
__disable_interrupt(); // запретить прерывания
if(!WatchReset) // пора перезапускать WatchDog
{
WatchReset = 200; // исходное
SendEvent(Complete,2); // генерить событие для WatchDog
}
if(flag) // признак принятого фрейма по RS485
{
flag = 0;
if(CRC16()) // если правильная контрольная сумма
SendEvent(FrameOfUART1,0,(void*)InputByffer); // генерить событие
}
__enable_interrupt(); // разрешить прерывания
}
//***** Подсчет контрольной суммы для ModBus ********
unsigned int UART1::CRC16(char* array, char num) // для передачи
{
char *Buf = array;
char BufLen = num;
unsigned int CRC;
char i,j;
CRC = 0xffff;
for (i=0;i {
CRC ^= Buf[i];
for (j=0;j<8;j++)
if (CRC&1) { CRC >>= 1; CRC ^= 0xa001; }
else CRC >>= 1;
}
return CRC;
}
//***** Подсчет контрольной суммы для ModBus ********
char UART1::CRC16(void) // для приема
{
char *Buf = InputByffer;
char BufLen = (char)(InputPtr-Buf-2);
unsigned int CRC;
CRC = CRC16(Buf, BufLen);
CRC ^= (Buf[BufLen]|(Buf[BufLen+1]<<8));
if(CRC) return 0; else return 0xff;
}
//***************************************************
UART1* UART1::UART1Ptr; // инициализация указателя
//***************** Создаем объект ******************
UART1 Uart1;



Составить ответ  |||  Конференция  |||  Архив

Ответы


Отправка ответа

Имя (обязательно): 
Пароль: 
E-mail: 
NoIX ключ Запомнить

Тема (обязательно):
Сообщение:

Ссылка на URL: 
Название ссылки: 

URL изображения: 


Rambler's Top100 Рейтинг@Mail.ru
Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание

E-mail: info@telesys.ru