Страница 1 из 1

Проблемы с UART2 на PIC18F45K22

Добавлено: Чт июл 06, 2017 12:40:23
R'j_395
Доброго дня, товарищи программисты-электронщики.
Помогите решить проблему, пожалуйста! Есть код, который включает пару релешек и считывает давление, эти действия он должен выполнять по командам, приходящим с 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;
}

Re: Проблемы с UART2 на PIC18F45K22

Добавлено: Чт июл 06, 2017 13:31:12
Аlex
Никак не могу понять почему.
Ничего удивительного. Ни Вы, ни тем более мы, не видим в коде практически ничего, что касается UART'а, всё скрыто в библиотечные функции.
Реализуйте всю работу с модулем сами, тогда можно будет прогнать в том же протеусе и посмотреть что происходит.
И ещё, вопросик. Что Вы хотели сделать вот этой конструкцией :

Код: Выделить всё

case 120:; break;
?
Просто интересно ... :roll:

Re: Проблемы с UART2 на PIC18F45K22

Добавлено: Чт июл 06, 2017 14:23:52
R'j_395
Код не мой. Мне достался по наследству от предыдущего разработчика..
Полагаю, что подразумевается, что ничего не надо делать, если пришёл символ "х", так как посылка имеет вид "R01x01x01xx!".
Почему тогда с первым уартом работает?
И что такое протеус?

Re: Проблемы с UART2 на PIC18F45K22

Добавлено: Чт июл 06, 2017 14:41:39
Аlex
R'j_395 писал(а):Почему тогда с первым уартом работает?
Дак вопрос в чём, почему с первым работает, или почему со вторым не работает ? :)
R'j_395 писал(а):И что такое протеус?
https://www.yandex.ru/yandsearch?clid=9 ... 99344883.1

Re: Проблемы с UART2 на PIC18F45K22

Добавлено: Чт июл 06, 2017 14:50:02
R'j_395
Аlex писал(а):R'j_395 писал(а):
Почему тогда с первым уартом работает?
Дак вопрос в чём, почему с первым работает, или почему со вторым не работает ?
Вопрос в том почему если мы работаем с первым уартом всё работает, а если меняем в коде основной программы первый на второй, при этом не меняя больше ничего, программа выходит из цикла после 5-10 секунд работы... :cry:

Re: Проблемы с UART2 на PIC18F45K22

Добавлено: Чт июл 06, 2017 15:27:57
Zhuk72
А при смене портов вы и названия битов меняете? Сейчас в прерывании имеется 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 не нужно. Уточните этот момент.
И еще совершенно непонятные манипуляции с Трисами в начальной инициализации. Сперва присваиваете значение целому регистру, а потом отдельно по битам.

Re: Проблемы с UART2 на PIC18F45K22

Добавлено: Сб июл 08, 2017 15:58:41
КРАМ
GIE нельзя разрешать в прерывании. И язык программирования тут не причем. При взведении флагов прерываний во время исполнения обработчика, сразу за установкой GIE последует вложенный вызов и порча контекста. У автора все работало, пока был один источник поерываний. Именно второй поверх первого и портил контекст и стек.
К слову, GIE автоматически гасится при входе в обработчик и устанавливается командой retfie при выходе из обработчика.
Этой командой завершается обработчик в обязательном порядке. В Си любой компилятор так и делает. Фигурная скобка закрывающая тело обраюотчика и есть эта команда+восстановление контекста.

Re: Проблемы с UART2 на PIC18F45K22

Добавлено: Сб июл 08, 2017 19:42:50
Zhuk72
Первое что я сделал, переходя с асм на Си, это проверил обработчик прерывания после компиляции в ХС8. Там были все сохранения, восстановления и retfie. А с другими средами и компиляторами я дел не имел, не знаю как и что. Но вот запрещать прерывания при входе - это уж точно лишнее, в любом языке.