[an error occurred while processing this directive]
Помогите решить проблему с ошибками при передаче по RS232
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

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

Отправлено arreg 10 октября 2006 г. 22:45

Есть устройство на mega128 (кварц KX-KT 14.7456 МГц, проверен анализатором спектра), MAX232ESE, Vcc=5В. Устройством управляет прога на PC на Builder 6.0. Скорость 115кбод и чётность - обязательны (условие ТЗ).

Проблема: периодически возникает ошибка чётности при передаче, причём, проверял на разных компах. На одном компе (4й пень, XP) ошибок нет в принципе, на двух других - по-разному. Под 98й виндой на старом ноутбуке ошибки очень часто идут, на ещё одном 4м пне под XP - только если изменить какие-нибудь параметры (при этом два раза происходит посылка всех параметров в устройство, а при возникновении ошибки - снова).
Обратите внимание: код ошибки чётности у меня имеет код (например) FE. Он и приходит периодически на PC. А если подвигать ScrollBar2, то почти однозначно. Но, повторюсь, на одном компьютере всё идёт без ошибок вообще!
И ещё момент. Если ошибка возникла, то без перезапуска программы она практически никогда не исчезает. Даже в варианте программыдля PC, когда есть принудительная остановка всех посылок на некоторое время (при этом, вроде бы, программа в устройстве производит сброс – через 1 мс, кажется).
Куски программ:

********************* Для меги128:

// Программируем UART на скорость 115200 бод (код=7 для CK=14.7456 МГц)
#define baud 7
UBRR1H = high(baud); UBRR1L = low(baud);
UCSR1A = (0< UCSR1B = (1< UCSR1C = (3< // Прерывания от UARTа не разрешаются

#define UART_TRANSMIT(b) { while ( !tstbit(UCSR1A,UDRE1) ); UDR1=(b); }

// Программируем Timer3 на частоту 1 кГц для работы протокола передачи:
TCCR3A=0;
TCCR3B=(1< #define OCR3A_code (unsigned int)(14745600.0/8.0/1000.0-1)
OCR3AH = high(OCR3A_code); OCR3AL = low(OCR3A_code);
TCCR3C=0; // OC3A,B,C(выходы МКК) - не задействованы
// прерывание запрещено

do {
static unsigned char Com,Chr,Byte1,Nbt=0;

while(tstbit(UCSR1A,RXC1)==0) { // Ожидание внешней команды:
if(tstbit(ETIFR,OCF3A)!=0) { // Обработка ограничения времени приёма команды:
TCCR3B=(1< setbit(ETIFR,OCF3A); // сбрасываем флаг перегрузки счётчика
if(Nbt!=0) { // байты не приняты до конца, а таймер закончил счёт:
if(Nbt!=100) { UART_TRANSMIT(Com); UART_TRANSMIT(0x04); } // отсутствуют параметры команды
else {} // не передаём код ошибки 04, т.к. уже был передан код сбоя
// чётности 01 или 02, или код несуществующей команды 03
Nbt=0;
}
}
} // конец ожидания команды.

if(tstbit(UCSR1A,UPE1)!=0) { // ошибка чётности:
Chr=UDR1;
if(Nbt==0) { UART_TRANSMIT(Chr); UART_TRANSMIT(0x01); }
else { UART_TRANSMIT(Com); UART_TRANSMIT(0x02); } // ошибки чётности
Nbt=100; // Переходим на приём остаточных данных (спама)до поступления следующей команды
// или окончания защитного интервала
}
else { // Анализ команды:
Chr=UDR1;
if( (Nbt>0) & (Chr>=0x80) ) { // ожидался параметр, а получена команда:
if(Nbt!=100) { UART_TRANSMIT(Com); UART_TRANSMIT(0x04); } // отсутствуют параметры команды
else {} // если был сбой по чётности, не передаём код ошибки 04, т.к. уже был передан код сбоя
// чётности 01 или 02 или код несуществующей команды 03
Nbt=0;
} // ... и начинаем анализ полученной команды:

switch(Nbt) {
case 0:
TCNT3H=0; TCNT3L=0; TCCR3B=(1< Com=Chr;
switch(Com) { // Анализ и выполнение команд, не имеющих дополнительных параметров:
case (0x84): // Выключение генератора тестового сигнала:
{...} UART_TRANSMIT(Com); UART_TRANSMIT(0x00); Nbt=0; break;
{...}
case (0x87): // Чтение сигнала захвата синтезатора:
UART_TRANSMIT(Com); UART_TRANSMIT(0x00); UART_TRANSMIT(Com); UART_TRANSMIT(tstbit(PINF,hSYNT1_nAUXOUT)!=0); Nbt=0; break;
{...}
case (0x93): // Чтение частоты генератора тестового сигнала:
UART_TRANSMIT(Com); UART_TRANSMIT(0x00);
UART_TRANSMIT(Com); UART_TRANSMIT((FreqGS>>7)&0x7f); UART_TRANSMIT(FreqGS&0x7f);
Nbt=0; break;
case 0x8e:
case 0x81:
Nbt=1; break;
default: // Несуществующая команда:
Nbt=100; UART_TRANSMIT(Com); UART_TRANSMIT(0x03); break;
}
break;
case 1: // Выполняем команду, если у неё 1-байтный дополнительный параметр:
Byte1=Chr;
switch(Com) {
case (0x8e):
UART_TRANSMIT(Com); UART_TRANSMIT(0x00);
__EEPUT(REF_GEN_STATE,(Byte1&0x3));
{...}
Nbt=0; break;
case 0x81:
Nbt=2; break;
default: // вообще-то, такой ситуации не может возникнуть
UART_TRANSMIT(Com); UART_TRANSMIT(0xff); Nbt=0; break;
}
break;
case 2: // Выполняем команду, если у неё 2-байтный дополнительный параметр:
switch(Com) {
case (0x81): // Установка частоты генератора тестового сигнала:
UART_TRANSMIT(Com); UART_TRANSMIT(0x00); FreqGS=((Byte1<<7)|Chr);
setbit(sPowerDown[0],sPDIB); sIFRdiv[0]=REF/1000000; sIFNdiv[0]=FreqGS*8;
Synth1((1<<2)|(1<<5)|(1<<8)); Nbt=0; break;
{...}
default: // вообще-то, такой ситуации не может возникнуть
UART_TRANSMIT(Com); UART_TRANSMIT(0xff); Nbt=0; break;
}
break;
default: // если Nbt>2. Если Nbt=100, это значит, что был сбой чётности и теперь мы принимаем "спам"
break;
} // Конец анализа команды
} // конец условия проверки чётности

} while (1==1);

}


********************* Для PC:

DWORD WINAPI LockBandSearch( LPVOID );
HANDLE ComThread; DWORD ThreadId;
bool ComThreadExit=false;

void __fastcall TForm1::FormActivate(TObject *Sender)
{
{...}
DCB ComType; COMMTIMEOUTS Timeouts;
ComPort=CreateFile("COM0",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL); break;
if (ComPort == INVALID_HANDLE_VALUE) Edit1->Text="Статус: Ошибка";
else {
Edit1->Text="Статус: ОК";
GetCommState(ComPort,&ComType);
ComType.BaudRate=CBR_115200; ComType.ByteSize=8;
ComType.Parity=EVENPARITY; ComType.fParity=true;
ComType.fErrorChar=true; ComType.ErrorChar=0xfe; // ВОТ ЭТО САМОЕ FE МНЕ И ПРИХОДИТ ПЕРИОДИЧЕСКИ
// (ИЛИ ЛЮБОЙ ДРУГОЙ КОД, КОТОРЫЙ Я СДЕСЬ ЗАДАЮ)
ComType.StopBits=ONESTOPBIT;
ComType.fDtrControl=DTR_CONTROL_DISABLE; ComType.fRtsControl=RTS_CONTROL_DISABLE;
ComType.fOutxCtsFlow=false; ComType.fOutxDsrFlow=false;
SetCommState(ComPort,&ComType);

GetCommTimeouts(ComPort,&Timeouts);
Timeouts.ReadIntervalTimeout=100; Timeouts.ReadTotalTimeoutMultiplier=10;
Timeouts.ReadTotalTimeoutConstant=100;
Timeouts.WriteTotalTimeoutMultiplier=0; Timeouts.WriteTotalTimeoutConstant=0;
SetCommTimeouts(ComPort,&Timeouts);
}

ComThread=CreateThread(NULL,0,LockBandSearch,this,NULL,&ThreadId);
}

/* Вот когда я этот ползунок меняю, ошибки начинают сыпаться только так.
Вообще-то у меня в программе таких ползунков три, и есть другие аналогичные элементы управления,
Просто я их сюда не включил, чтобы не загромождать текст.
*/
void __fastcall TForm1::ScrollBarN1Change(TObject *Sender)
{ EditN1->Text=IntToStr(ScrollBarN1->Position)+" МГц"; FlagRenewState=2; }


DWORD WINAPI LockBandSearch( LPVOID ) {
char i;

do {
ErrCom=0;
if(FlagRenewState!=0) { // этот кусок выполняется два раза, если изменить какие-нибудь параметры:
FlagRenewState--;
if(Form1->ButtonN1->Caption=="Вкл") {
BytesToW[0]=0x81; BytesToW[1]=((Form1->ScrollBarN1->Position)>>7)&0x7f; BytesToW[2]=((Form1->ScrollBarN1->Position)>>0)&0x7f;
WriteFile(ComPort,&BytesToW,3,&nCharWait,NULL);
if(ReadFile(ComPort,&BytesToR,2,&nCharWait,NULL)==false) ErrCom=1;
else if( (BytesToR[1]!=0)|(nCharWait!=2) ) ErrCom=2;
else if(BytesToR[0]!=BytesToW[0]) ErrCom=3;
}
else {
BytesToW[0]=0x84; WriteFile(ComPort,&BytesToW,1,&nCharWait,NULL);
if(ReadFile(ComPort,&BytesToR,2,&nCharWait,NULL)==false) ErrCom=1;
else if( (BytesToR[1]!=0)|(nCharWait!=2) ) ErrCom=2;
else if(BytesToR[0]!=BytesToW[0]) ErrCom=3;
}
{...}
}

{...}

if(fWriteRefGen==1) {
BytesToW[0]=0x8e; BytesToW[1]=Form1->ComboBoxN5->ItemIndex;
WriteFile(ComPort,&BytesToW,2,&nCharWait,NULL);
if(ReadFile(ComPort,&BytesToR,2,&nCharWait,NULL)==false) ErrCom=1;
else if( (BytesToR[1]!=0)|(nCharWait!=2) ) ErrCom=1;
else if(BytesToR[0]!=BytesToW[0]) ErrCom=1;
fWriteRefGen=0;
}

{ // Чтение сигналов захвата. Этот кусок выполняется постоянно.
Sleep(1); // Ждём, пока установится частота
BytesToW[0]=0x87; WriteFile(ComPort,&BytesToW,1,&nCharWait,NULL);
if( (ReadFile(ComPort,&BytesToR,4,&nCharWait,NULL)==false) | (BytesToR[0]!=BytesToW[0]) | (BytesToR[2]!=BytesToW[0]) |
(BytesToR[1]!=0) | (nCharWait!=4) )
{ ErrCom=1; Form1->EditN2b->Text="Захват1: ???"; }
else {
if(BytesToR[3]!=0) Form1->EditN2b->Text="Захват1: OK"; else Form1->EditN2b->Text="Захват1: NO";
}

{...}

}


if(ErrCom!=0) { FlagRenewState=2; Form1->Edit3->Text="Ошибка передачи данных "+IntToStr(ErrCom)+" "+IntToStr(BytesToR[1]); }
else Form1->Edit3->Text="Передача данных: ОК";

} while(ComThreadExit==false);
ExitThread(0); return(0);
}


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

Ответы


Отправка ответа
Имя (обязательно): 
Пароль: 
E-mail: 

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

Ссылка на URL: 
Название ссылки: 
URL изображения: 


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