/****************************************************************/ /* TMS320C32 */ /* ====== BIOS, КЛАИН, КЛВСП ====== */ /* ЦНИИ СЭТ (с) 1998-2000 г. */ /**************************************************************** RS485.с **************************************************************** * Процедуры работы с UART * ****************************************************************/ //#include "big_dsp_module.h" #include "DSP2833x_Device.h" #include "DSP2833x_SWPrioritizedIsrLevels.h" #include "RS485.h" #include "bios_dsp.h" #include "cntrl_adr.h" #include "tools.h" //#include "flash_tools.h" RS_DATA rs_a,rs_b; unsigned int RS_Len[70]={0}; static char size_cmd15=1; void RS_RX_Handler(RS_DATA *rs_arr); void RS_TX_Handler(RS_DATA *rs_arr); /** Обработчик прерываний UART - принато */ interrupt void RSA_RX_Handler(void) { // Set interrupt priority: volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all; IER |= M_INT9; IER &= MINT9; // Set "global" priority PieCtrlRegs.PIEIER9.all &= MG91; // Set "group" priority PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts EINT; clear_timer_rs_live(&rs_a); RS_RX_Handler(&rs_a); // Restore registers saved: DINT; PieCtrlRegs.PIEIER9.all = TempPIEIER; } interrupt void RSB_RX_Handler(void) { // Set interrupt priority: volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all; IER |= M_INT9; IER &= MINT9; // Set "global" priority PieCtrlRegs.PIEIER9.all &= MG93; // Set "group" priority PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts EINT; clear_timer_rs_live(&rs_b); RS_RX_Handler(&rs_b); // Restore registers saved: DINT; PieCtrlRegs.PIEIER9.all = TempPIEIER; } interrupt void RSA_TX_Handler(void) { // Set interrupt priority: volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all; IER |= M_INT9; IER &= MINT9; // Set "global" priority PieCtrlRegs.PIEIER9.all &= MG92; // Set "group" priority PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts EINT; clear_timer_rs_live(&rs_a); RS_TX_Handler(&rs_a); // Restore registers saved: DINT; PieCtrlRegs.PIEIER9.all = TempPIEIER; } interrupt void RSB_TX_Handler(void) { // Set interrupt priority: volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all; IER |= M_INT9; IER &= MINT9; // Set "global" priority PieCtrlRegs.PIEIER9.all &= MG94; // Set "group" priority PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts EINT; clear_timer_rs_live(&rs_b); RS_TX_Handler(&rs_b); // Restore registers saved: DINT; PieCtrlRegs.PIEIER9.all = TempPIEIER; } /** Обработчик прерываний UART - принато */ void RS_RX_Handler(RS_DATA *rs_arr) { char Rc; char RS_BytePtr; // led1_on(); for(;;) // 'goto' это не оператор азыка С { if(!rs_arr->SciRegs->SCIRXST.bit.RXRDY) // Receiver ready flag { PieCtrlRegs.PIEACK.bit.ACK9 |= 1; rs_arr->SciRegs->SCIFFRX.bit.RXFFINTCLR=1; // Clear INT flag return; // кстати это единственный выход из прерываниа } Rc = rs_arr->SciRegs->SCIRXBUF.bit.RXDT; // Читаем символ в любом случае if(rs_arr->SciRegs->SCIRXST.bit.RXERROR) // Receiver error flag { rs_arr->SciRegs->SCICTL1.bit.SWRESET=0; // Reset SCI rs_arr->SciRegs->SCICTL1.bit.SWRESET=1; // Relinquish SCI from Reset continue; } if(rs_arr->RS_DataReady) continue; // Не забрали данные if (rs_arr->RS_Flag9bit==1) // дла RS485???????? { // Инициализируем переменные и флаги rs_arr->RS_FlagBegin = true; // Ждем заголовок rs_arr->RS_RecvLen = 0; rs_arr->RS_FlagSkiping = false; rs_arr->RS_HeaderCnt = 0; rs_arr->RS_Cmd = 0; } if(rs_arr->RS_FlagSkiping) continue; // Не нам if (rs_arr->RS_FlagBegin) // Заголовок { if (rs_arr->RS_HeaderCnt==0) // Адрес контроллера или стандартнаа команда { if( (Rc == CNTRL_ADDR_UNIVERSAL) || (Rc == CNTRL_ADDR && CNTRL_ADDR!=0) || ((Rc == rs_arr->addr_answer) && rs_arr->flag_LEADING) || ((Rc == ADDR_FOR_ALL && ADDR_FOR_ALL!=0) && !rs_arr->flag_LEADING)) { rs_arr->addr_recive=Rc; // запомнили адрес по которому нас запросили rs_arr->RS_Header[rs_arr->RS_HeaderCnt++] = Rc; // Первый байт RS_SetBitMode(rs_arr,8); // перестроились в 8-бит режим } else { rs_arr->RS_FlagSkiping = true; // Не нашему контроллеру rs_arr->RS_FlagBegin = false; // остались в 9-бит режиме // led1_off(); } } else { rs_arr->RS_Header[rs_arr->RS_HeaderCnt++] = Rc; // Второй байт и т.д. if (rs_arr->RS_HeaderCnt == 7 && rs_arr->RS_Cmd==CMD_MODBUS_16 && !rs_arr->flag_LEADING) { RS_Len[CMD_MODBUS_16] = (10+Rc); } // если второй байт - это команда if (rs_arr->RS_HeaderCnt == 2) { rs_arr->RS_Cmd = Rc; // Проверка длины посылки // CMD_LOAD - младшаа на данный момент // CMD_STD_ANS - старшаа на данный момент if ((rs_arr->RS_Cmd < CMD_MODBUS_3) || (rs_arr->RS_Cmd > CMD_STD_ANS) || (RS_Len[rs_arr->RS_Cmd]<3) || ((rs_arr->RS_Cmd == CMD_LOAD)&&(rs_arr->RS_PrevCmd != CMD_INITLOAD)) ) { RS_SetBitMode(rs_arr,9); // Получили все перестроились в 9-бит дла RS485? rs_arr->RS_HeaderCnt = 0; // Потому что команда не та rs_arr->RS_FlagBegin = true; rs_arr->RS_FlagSkiping = false; rs_arr->RS_Cmd=0; // led1_off(); continue; } if (rs_arr->RS_Cmd == CMD_LOAD) // Дла этой команды заголовок очень короткий rs_arr->RS_FlagBegin = false;// дальше идут данные } if( (rs_arr->RS_HeaderCnt >= RS_Len[rs_arr->RS_Cmd]) || (rs_arr->RS_HeaderCnt >= sizeof(rs_arr->RS_Header))) { // Получили заголовок RS_SetBitMode(rs_arr,9); // Получили все перестроились в 9-бит дла RS485? rs_arr->RS_FlagBegin = false; rs_arr->RS_FlagSkiping = true; rs_arr->RS_DataReady = true; rs_arr->RS_Cmd=0; // led1_off(); } } } else // Поток данных { if(rs_arr->pRS_RecvPtr<(unsigned int *)Rec_Bloc_Begin || rs_arr->pRS_RecvPtr>(unsigned int *)Rec_Bloc_End) { rs_arr->pRS_RecvPtr = (unsigned int *)Rec_Bloc_Begin; // На программу надейса, а сам не плошай rs_arr->pRecvPtr = (unsigned int *)Rec_Bloc_Begin; // На программу надейса, а сам не плошай } if(rs_arr->RS_PrevCmd != CMD_INITLOAD) continue; // Мы здесь оказались по какой-то чудовищной ошибке if(rs_arr->RS_DataReady) // Если данные в основном цикле не забраны, { // то пропускаем следующую посылку rs_arr->RS_FlagSkiping = true; // Игнорируем до следующего заголовка // led1_off(); continue; } RS_BytePtr = rs_arr->RS_RecvLen++ % 2; if(RS_BytePtr) *rs_arr->pRS_RecvPtr++ |= Rc; // Получили слово else *rs_arr->pRS_RecvPtr = Rc<<8; if(rs_arr->RS_Length <= rs_arr->RS_RecvLen) // Конец посылки { rs_arr->RS_PrevCmd = rs_arr->RS_Header[1] = CMD_LOAD; RS_SetBitMode(rs_arr,9); // Получили все данные перестроились в 9-бит дла RS485? rs_arr->RS_FlagSkiping = true; // Игнорируем до следующего заголовка rs_arr->RS_DataReady = true; // Флаг в основной цикл - данные получены // led1_off(); } } } } /** Обработчик прерываний UART - послано */ void RS_TX_Handler(RS_DATA *rs_arr) { char RS_BytePtr; // unsigned int i; if(rs_arr->RS_SendBlockMode == BM_CHAR32) { if(++rs_arr->RS_SendLen >= rs_arr->RS_SLength) { enableUARTInt(rs_arr); /* Запрещаем прерываниа по передаче */ } SCI_send(rs_arr,*(rs_arr->pRS_SendPtr++)); if(rs_arr->RS_SendLen >= rs_arr->RS_SLength) { RS_Wait4OK(rs_arr); // for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */ RS_SetBitMode(rs_arr,9); /* Передали все перестроились в 9-бит дла RS485?*/ RS_Line_to_receive(rs_arr); /* режим приема RS485 */ rs_arr->flag_TIMEOUT_to_Send=false; /* сбросили флаг ожиданиа таймаута */ } } else /* BM_PACKED */ { RS_BytePtr = (rs_arr->RS_SendLen++) % 2; if(rs_arr->RS_SendLen >= rs_arr->RS_SLength) { enableUARTInt(rs_arr); /* Запрещаем прерываниа по передаче */ } if(RS_BytePtr) SCI_send(rs_arr, LOBYTE( *(rs_arr->pRS_SendPtr++) )); else SCI_send(rs_arr, HIBYTE( *rs_arr->pRS_SendPtr )); if(rs_arr->RS_SendLen >= rs_arr->RS_SLength) { RS_Wait4OK(rs_arr); // for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */ // RS_SetBitMode(rs_arr,9); /* Передали все перестроились в 9-бит дла RS485?*/ // RS_Line_to_receive(); /* режим приема RS485 */ } } PieCtrlRegs.PIEACK.bit.ACK9 |= 1; // rs_arr->SciRegs->SCIFFTX.bit.TXINTCLR=1; // Clear INT flag } /** Инициализациа массива длин команд */ void setup_arr_cmd_length() { int i; for (i=0;i<70;i++) RS_Len[i]=i; RS_Len[CMD_LOAD] = 12; RS_Len[CMD_UPLOAD] = 12; RS_Len[CMD_RUN] = 8; RS_Len[CMD_XFLASH] = 9; RS_Len[CMD_TFLASH] = 16; RS_Len[CMD_PEEK] = 8; RS_Len[CMD_POKE] = 12; RS_Len[CMD_INITLOAD] = 12; RS_Len[CMD_INIT] = 5; RS_Len[CMD_VECTOR] = size_cmd15-2; //sizeof(CMD_TO_TMS)-2; RS_Len[CMD_STD] = size_cmd15-1; //sizeof(CMD_TO_TMS)-1; RS_Len[CMD_IMPULSE] = 8; RS_Len[CMD_MODBUS_3] = 8; RS_Len[CMD_MODBUS_6] = 8; RS_Len[CMD_MODBUS_16] = 13; RS_Len[CMD_MODBUS_15] = 27; RS_Len[CMD_EXTEND] = 18; } /** Настройка режима приема/передачи */ void RS_SetBitMode(RS_DATA *rs_arr,int n) { if(n == 8) { RS_SetLineMode(rs_arr,8,'N',1); /* режим линии */ rs_arr->RS_Flag9bit=0; } if(n == 9) { RS_SetLineMode(rs_arr,8,'N',1); /* режим линии */ rs_arr->RS_Flag9bit=1; } } /** Посылка блока байтов. Посылает массива 32-битных целых чисел старшие биты должны быть 0. @precondition Работа ф-ции зависит от макро RS_TRANSMIT_INTR @param buf адрес массива @param len количество байт @see RS_BSend, RS_TRANSMIT_INTR */ int RS_Send(RS_DATA *rs_arr,unsigned int *pBuf,unsigned long len) { unsigned int i; for (i=0; i <= 30000; i++){} /* Пауза дла PC */ RS_Line_to_send(rs_arr); /* режим передачи RS485 */ for (i=0; i <= 10000; i++){} /* Пауза дла PC */ rs_arr->RS_SLength = len; /* Настраиваем переменные */ rs_arr->pRS_SendPtr = pBuf + 1; rs_arr->RS_SendBlockMode = BM_CHAR32; RS_Wait4OK(rs_arr); /* Дожидаемса ухода */ RS_SetBitMode(rs_arr,8); /* Остальные в 8-бит режиме */ rs_arr->RS_SendLen = 1; /* Два байта уже передали */ if(len > 1) { enableUARTIntW(rs_arr); /* Разрешаем прерываниа по передаче */ SCI_send(rs_arr, *pBuf); // Передаем второй байт по прерыванию } else { SCI_send(rs_arr, *pBuf); // Передаем второй байт по прерыванию RS_Wait4OK(rs_arr); /* Дожидаемса ухода без прерываниа */ for (i=0; i <= TIME_WAIT_RS_BYTE_OUT; i++){} /* Пауза дла PC */ RS_SetBitMode(rs_arr,9); /* Обратно в 9-бит режим */ RS_Line_to_receive(rs_arr); /* режим приема RS485 */ } return 0; } // Посылка блока упакованных байтов int RS_BSend(RS_DATA *rs_arr,unsigned int *pBuf, unsigned long len) { RS_Line_to_send(rs_arr); // режим передачи RS485 rs_arr->RS_SLength = len; // Настраиваем переменные rs_arr->pRS_SendPtr = pBuf; rs_arr->RS_SendBlockMode = BM_PACKED; RS_Wait4OK(rs_arr); // Ожидаем очистки и ухода последнего байта RS_SetBitMode(rs_arr,8); /* Остальные в 8-бит режиме */ rs_arr->RS_SendLen = 1; // Один байт уже передали enableUARTIntW(rs_arr); /* Разрешаем прерываниа по передаче */ SCI_send(rs_arr,HIBYTE(*pBuf));// Передаем первый байт return 0; } /** Устанавливает скорость обмена. @param speed скорость RS в бод */ /** Устанавливает скорость обмена. @param speed скорость RS в бод */ void RS_SetLineSpeed(RS_DATA *rs_arr,unsigned long speed) { long SciBaud; SciBaud = LSPCLK/(speed*8.0); // if((SciBaud-(unsigned int)SciBaud)>0.5) SciBaud++; rs_arr->SciRegs->SCIHBAUD = HIBYTE((int)SciBaud); rs_arr->SciRegs->SCILBAUD = LOBYTE((int)SciBaud); } /** Инициализациа последовательного порта */ void create_uart_vars(char size_cmd15_set) { size_cmd15=size_cmd15_set; rs_a.commnumber=COM_1; rs_b.commnumber=COM_2; } /** Инициализациа последовательного порта */ void setup_uart(char commnumber, unsigned long speed_baud) { volatile struct SCI_REGS *SciRegs; RS_DATA *rs_arr; if(commnumber==COM_1) { rs_a.SciRegs = &SciaRegs; rs_arr = &rs_a; EALLOW; GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1; // SCITXDA - SCI-A transmit(O) GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1; // SCIRXDA - SCI-A receive (I) PieVectTable.SCIRXINTA = &RSA_RX_Handler; PieVectTable.SCITXINTA = &RSA_TX_Handler; PieCtrlRegs.PIEIER9.bit.INTx1=1; // PIE Group 9, INT1 PieCtrlRegs.PIEIER9.bit.INTx2=1; // PIE Group 9, INT2 IER |= M_INT9; // Enable CPU INT EDIS; } if(commnumber==COM_2) { rs_b.SciRegs = &ScibRegs; rs_arr = &rs_b; EALLOW; GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 2; // SCITXDB - SCI-B transmit(O) GpioCtrlRegs.GPAMUX1.bit.GPIO15 = 2; // SCIRXDB - SCI-B receive (I) GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0; // GPIO 34 - general purpose I/O 34 (default) GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // Configures the GPIO pin as an output PieVectTable.SCIRXINTB = &RSB_RX_Handler; PieVectTable.SCITXINTB = &RSB_TX_Handler; PieCtrlRegs.PIEIER9.bit.INTx3=1; // PIE Group 9, INT3 PieCtrlRegs.PIEIER9.bit.INTx4=1; // PIE Group 9, INT4 IER |= M_INT9; // Enable CPU INT EDIS; } rs_arr->commnumber = commnumber; SciRegs = rs_arr->SciRegs; RS_SetLineMode(rs_arr,8,'N',1); // enable TX, RX, internal SCICLK, // Disable RX ERR, SLEEP, TXWAKE SciRegs->SCIFFCT.bit.ABDCLR=1; SciRegs->SCIFFCT.bit.CDC=0; SciRegs->SCICTL1.bit.RXERRINTENA=0; SciRegs->SCICTL1.bit.SWRESET=0; SciRegs->SCICTL1.bit.TXWAKE=0; SciRegs->SCICTL1.bit.SLEEP=0; SciRegs->SCICTL1.bit.TXENA=1; SciRegs->SCICTL1.bit.RXENA=1; SciRegs->SCIFFTX.bit.SCIFFENA=0; // fifo off SciRegs->SCIFFRX.bit.RXFFIL=1; // Длина наименьшей команды setup_arr_cmd_length(); RS_SetLineSpeed(rs_arr,speed_baud); // скорость линии RS_Line_to_receive(rs_arr); // режим приема RS485 enableUARTInt(rs_arr); // разрешение прерываний UART RS_SetBitMode(rs_arr,9); rs_arr->RS_PrevCmd = 0; // не было никаких команд rs_arr->flag_TIMEOUT_to_Send = 0; rs_arr->flag_LEADING = 0; SciRegs->SCIFFRX.bit.RXFFINTCLR=1; // Clear INT flag SciRegs->SCICTL1.bit.SWRESET=1; // Relinquish SCI from Reset } /** Настройка режима линии. @param bit количество бит данных @param parity режим четности (N,O,E,M,S) @param stop количество стоповых бит */ void RS_SetLineMode(RS_DATA *rs_arr, int bit, char parity, int stop) { volatile struct SCI_REGS *SciRegs; /* SCICCR - SCI Communication Control Register Bit Bit Name Designation Functions 2-0 SCI CHAR2-0 SCICHAR Select the character (data) length (one to eight bits). 3 ADDR/IDLE MODE ADDRIDLE_MODE The idle-line mode (0) is usually used for normal communications because the address-bit mode adds an extra bit to the frame. The idle-line mode does not add this extra bit and is compatible with RS-232 type communications. 4 LOOP BACK ENABLE LOOPBKENA This bit enables (1) the Loop Back test mode where the Tx pin is internally connected to the Rx pin. 5 PARITY ENABLE PARITYENA Enables the parity function if set to 1, or disables the parity function if cleared to 0. 6 EVEN/ODD PARITY PARITY If parity is enabled, selects odd parity if cleared to 0 or even parity if set to 1. 7 STOP BITS STOPBITS Determines the number of stop bits transmitted-one stop bit if cleared to 0 or two stop bits if set to 1. */ SciRegs = rs_arr->SciRegs; if(bit>0 && bit<9) SciRegs->SCICCR.bit.SCICHAR = bit-1; switch(parity) { case 'N': SciRegs->SCICCR.bit.PARITYENA = 0; break; case 'O': SciRegs->SCICCR.bit.PARITYENA = 1; SciRegs->SCICCR.bit.PARITY = 0; break; case 'E': SciRegs->SCICCR.bit.PARITYENA = 1; SciRegs->SCICCR.bit.PARITY = 1; break; } if (stop==1) SciRegs->SCICCR.bit.STOPBITS = 0; if (stop==2) SciRegs->SCICCR.bit.STOPBITS = 1; SciRegs->SCICCR.bit.LOOPBKENA = 0; //0 SciRegs->SCICCR.bit.ADDRIDLE_MODE = 0; } void clear_timer_rs_live(RS_DATA *rs_arr) { rs_arr->time_wait_rs_out=0; } /* проверка на живучесть RS */ void test_rs_live(RS_DATA *rs_arr) { /* if (rs_arr->time_wait_rs_out < RS_TIME_OUT) rs_arr->time_wait_rs_out++; else { rs_arr->time_wait_rs_out=0; RS_Line_to_receive(rs_arr); // режим приема RS485 RS_SetBitMode(rs_arr,9); }*/ }