Форум РадиоКот https://radiokot.ru/forum/ |
|
Проблемы с UART2 на PIC18F45K22 https://radiokot.ru/forum/viewtopic.php?f=58&t=146575 |
Страница 1 из 1 |
Автор: | R'j_395 [ Чт июл 06, 2017 12:40:23 ] |
Заголовок сообщения: | Проблемы с UART2 на PIC18F45K22 |
Доброго дня, товарищи программисты-электронщики. Помогите решить проблему, пожалуйста! Есть код, который включает пару релешек и считывает давление, эти действия он должен выполнять по командам, приходящим с UART'а. Однако, проблема в том, что при подключении второго UART'a цикл основной программы прекращается. Никак не могу понять почему. Если передавать данные по первому UART'y, всё прекрасно работает и на приём, и на передачу. Однако, при подключении второго, программа выходит из цикла и поэтому, UART не передаёт данные обратно на компьютер, при этом, принимая их и производя необходимые действия. Текст основной программы в среде microC PRO for PIC Код: #define timeout1 500000 #define timeout2 1000000 #include "main.h" int disconnected = 1; int ping=0; volatile char ID='1'; volatile int sendPress=0; volatile int sendRele=0; volatile int sendID=0; volatile int uartN = 0; char relArr[10]; void meas_press(); void interrupt(void) { if(RC1IF_bit){ ping=0; INTCON.GIE = 0; RC1IF_bit = 0; delay_us(5); uart2_read_text(uart_r, "!", 20); if(uart_r[0]==36) //$ { disconnected =1; } if(uart_r[0]==82) //R { relay_set(uart_r); } if(uart_r[0]==80) //P { sendPress=1; } if(uart_r[0]==42) //* { sendID=1; } if(uart_r[0]==73) //I { ID=uart_r[1]; } } INTCON.GIE = 1; } void initialisation_relmod(void){ RELAY_1 = 0; RELAY_2 = 0; RELAY_3 = 0; RELAY_4 = 0; RELAY_5 = 0; RELAY_6 = 0; RELAY_7 = 0; RELAY_8 = 0; RELAY_9 = 0; RELAY_10 = 0; CS1 = 1; CS2 = 1; CS3 = 1; } void adc_select(int ch){ switch(ch){ case 0: CHS0_bit = 0; CHS1_bit = 0; CHS2_bit = 0; break; //select AN0 case 1: CHS0_bit = 1; CHS1_bit = 0; CHS2_bit = 0; break; //select AN1 case 2: CHS0_bit = 0; CHS1_bit = 1; CHS2_bit = 0; break; //select AN2 case 3: CHS0_bit = 1; CHS1_bit = 1; CHS2_bit = 0; break; //select AN3 case 4: CHS0_bit = 0; CHS1_bit = 0; CHS2_bit = 1; break; //select AN4 case 5: CHS0_bit = 1; CHS1_bit = 0; CHS2_bit = 1; break; //select AN5 } } void meas_press(){ //расчёт давления for (i = 0; i < 6; i++){ adc_select(i); ADON_bit = 1; GO_DONE_bit = 1; delay_ms(2); for (j = 0; j < 30; j++){ if(GO_DONE_bit == 0){ admes[i][j] = ADRESH; GO_DONE_bit = 1; delay_ms(2); } } ADON_bit = 0; } uart2_write(80); for (i = 0; i < 6; i++){ for (j = 0; j < 30; j++){ sum[i] += admes[i][j]; } sum[i] = sum[i]/30; uart2_write(sum[i]); } uart2_write(33); } void relay_set(char uart_rd[12]) //Функция изменения состояний реле { int ct=0; switch(uart_rd[1]){ case 48:{ RELAY_1 = 0; relArr[0]='0'; break; } case 49:{ RELAY_1 = 1; relArr[0]='1'; break; } case 120:; break; } switch(uart_rd[2]){ case 48:{ RELAY_2 = 0; relArr[1]='0'; break;} case 49:{ RELAY_2 = 1; relArr[1]='1'; break;} case 120:; break; } switch(uart_rd[3]){ case 48:{ RELAY_3 = 0; relArr[2]='0'; break;} case 49:{ RELAY_3 = 1; relArr[2]='1'; break;} case 120:; break; } switch(uart_rd[4]){ case 48:{ RELAY_4 = 0; relArr[3]='0'; break;} case 49:{ RELAY_4 = 1; relArr[3]='1'; break;} case 120:; break; } switch(uart_rd[5]){ case 48:{ RELAY_5 = 0; relArr[4]='0'; break;} case 49:{ RELAY_5 = 1; relArr[4]='1'; break;} case 120:; break; } switch(uart_rd[6]){ case 48:{ RELAY_6 = 0; relArr[5]='0'; break;} case 49:{ RELAY_6 = 1; relArr[5]='1'; break;} case 120:; break; } switch(uart_rd[7]){ case 48:{ RELAY_7 = 0; relArr[6]='0'; break;} case 49:{ RELAY_7 = 1; relArr[6]='1'; break;} case 120:; break; } switch(uart_rd[8]){ case 48:{ RELAY_8 = 0; relArr[7]='0'; break;} case 49:{ RELAY_8 = 1; relArr[7]='1'; break;} case 120:; break; } switch(uart_rd[9]){ case 48:{ RELAY_9 = 0; relArr[8]='0'; break;} case 49:{ RELAY_9 = 1; relArr[8]='1'; break;} case 120:; break; } switch(uart_rd[10]){ case 48:{ RELAY_10 = 0; relArr[9]='0'; break;} case 49:{ RELAY_10 = 1; relArr[9]='1'; break;} case 120:; break; } sendRele=1; } void main(void){ int ct=0; reg_ini(); initialisation_relmod(); initialisation_usart(); start_ISR(); INTCON.GIE=1; while(1) { uart2_write_text("Text"); //отправляет текст для проверки находится ли программа в цикле if(sendPress) { meas_press(); sendPress=0; } if(sendRele) { uart2_write('R'); for(ct=0;ct<10;ct++) { uart2_write(relArr[ct]); } uart2_write('!'); sendRele=0; } delay_ms(100); if(sendID) { uart2_write(35); uart2_write(ID); uart2_write('!'); sendID=0; } } } Текст файла инициализации в той же программе Код: /*****************************************************************************/
/* Функция инициализации регистров */ /*****************************************************************************/ void reg_ini(void){ ANSELA = 0x2F; ANSELE = 0x07; ANSELB = 0x00; ANSELC = 0x00; ANSELD = 0x00; OSCCON.SCS0 = 0; OSCCON.SCS1 = 0; OSCCON2.PLLRDY = 1; OSCCON2.PLLEN = 1; TRISC = 0xC0; TRISD = 0xC0; PORTC = 0x00; PORTD = 0x00; TRISA = 0x2F; TRISE = 0x07; TRISB0_bit = 0; TRISB1_bit = 0; TRISB2_bit = 0; TRISB3_bit = 0; TRISB4_bit = 0; TRISB5_bit = 0; TRISC1_bit = 0; TRISC2_bit = 0; TRISC.F6 = 0; TRISC.F7 = 1; TRISD0_bit = 1; TRISD1_bit = 1; TRISD2_bit = 1; TRISD4_bit = 0; TRISD5_bit = 0; TRISD.F6 = 0; TRISD.F7 = 1; ADCON0 = 0x03; ADCON1 = 0x00; ADCON2 = 0b00010110; INTCON = 0x00; RCON.IPEN = 0; TMR0L = 0; } /*****************************************************************************/ /* Функция инициализации USART1->FT232RL to USB & USART2->Terminal */ /*****************************************************************************/ void initialisation_usart(void){ UART1_Init(38400); UART2_Init(38400); } /*****************************************************************************/ /* Функция запуска прерываний и таймера */ /*****************************************************************************/ void start_ISR(void){ PIR1 = 0x00; INTCON = 0xE0; PIE1 = 0x20; IPR1 = 0x00; } |
Автор: | Аlex [ Чт июл 06, 2017 13:31:12 ] |
Заголовок сообщения: | Re: Проблемы с UART2 на PIC18F45K22 |
Цитата: Никак не могу понять почему. Ничего удивительного. Ни Вы, ни тем более мы, не видим в коде практически ничего, что касается UART'а, всё скрыто в библиотечные функции.Реализуйте всю работу с модулем сами, тогда можно будет прогнать в том же протеусе и посмотреть что происходит. И ещё, вопросик. Что Вы хотели сделать вот этой конструкцией : Код: case 120:; break; ? Просто интересно ... ![]() |
Автор: | R'j_395 [ Чт июл 06, 2017 14:23:52 ] |
Заголовок сообщения: | Re: Проблемы с UART2 на PIC18F45K22 |
Код не мой. Мне достался по наследству от предыдущего разработчика.. Полагаю, что подразумевается, что ничего не надо делать, если пришёл символ "х", так как посылка имеет вид "R01x01x01xx!". Почему тогда с первым уартом работает? И что такое протеус? |
Автор: | Аlex [ Чт июл 06, 2017 14:41:39 ] |
Заголовок сообщения: | Re: Проблемы с UART2 на PIC18F45K22 |
R'j_395 писал(а): Почему тогда с первым уартом работает? Дак вопрос в чём, почему с первым работает, или почему со вторым не работает ? ![]() R'j_395 писал(а): И что такое протеус? https://www.yandex.ru/yandsearch?clid=9 ... 99344883.1
|
Автор: | R'j_395 [ Чт июл 06, 2017 14:50:02 ] |
Заголовок сообщения: | Re: Проблемы с UART2 на PIC18F45K22 |
Аlex писал(а): R'j_395 писал(а): Почему тогда с первым уартом работает? Дак вопрос в чём, почему с первым работает, или почему со вторым не работает ? Вопрос в том почему если мы работаем с первым уартом всё работает, а если меняем в коде основной программы первый на второй, при этом не меняя больше ничего, программа выходит из цикла после 5-10 секунд работы... ![]() |
Автор: | Zhuk72 [ Чт июл 06, 2017 15:27:57 ] |
Заголовок сообщения: | Re: Проблемы с UART2 на PIC18F45K22 |
А при смене портов вы и названия битов меняете? Сейчас в прерывании имеется RC1IF и обращение uart2. Может где-то что-то забываете заменить? И еще кое-что. В прерывании у вас какие-то длинные операции. После очистки флага приема поставьте метку и выходите оттуда, а основном цикле проверяйте ее и проделывайте чтение. СпойлерКод: char read_port = 0; void interrupt(void) { if(RC1IF_bit) { ping=0; RC1IF_bit = 0; read_port = 1; } } void main(void) { .... if(read_port) { read_port = 0; uart2_read_text(uart_r, "!", 20); if(uart_r[0]==36) //$ { disconnected =1; } if(uart_r[0]==82) //R { relay_set(uart_r); } if(uart_r[0]==80) //P { sendPress=1; } if(uart_r[0]==42) //* { sendID=1; } if(uart_r[0]==73) //I { ID=uart_r[1]; } } } Вообще удобнее создать структуру и назначить биты в виде флагов вместо целых переменных. Память не резиновая, даже в таком ПИКе. Не знаю как в вашем МикроСи, но скорее всего в прерывании запрещать и разрешать бит GIE не нужно. Уточните этот момент. И еще совершенно непонятные манипуляции с Трисами в начальной инициализации. Сперва присваиваете значение целому регистру, а потом отдельно по битам. |
Автор: | КРАМ [ Сб июл 08, 2017 15:58:41 ] |
Заголовок сообщения: | Re: Проблемы с UART2 на PIC18F45K22 |
GIE нельзя разрешать в прерывании. И язык программирования тут не причем. При взведении флагов прерываний во время исполнения обработчика, сразу за установкой GIE последует вложенный вызов и порча контекста. У автора все работало, пока был один источник поерываний. Именно второй поверх первого и портил контекст и стек. К слову, GIE автоматически гасится при входе в обработчик и устанавливается командой retfie при выходе из обработчика. Этой командой завершается обработчик в обязательном порядке. В Си любой компилятор так и делает. Фигурная скобка закрывающая тело обраюотчика и есть эта команда+восстановление контекста. |
Автор: | Zhuk72 [ Сб июл 08, 2017 19:42:50 ] |
Заголовок сообщения: | Re: Проблемы с UART2 на PIC18F45K22 |
Первое что я сделал, переходя с асм на Си, это проверил обработчик прерывания после компиляции в ХС8. Там были все сохранения, восстановления и retfie. А с другими средами и компиляторами я дел не имел, не знаю как и что. Но вот запрещать прерывания при входе - это уж точно лишнее, в любом языке. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |