Например TDA7294

Форум РадиоКот :: Просмотр темы - Проблемы с UART2 на PIC18F45K22
Форум РадиоКот
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;
?
Просто интересно ... :roll:

Автор:  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 секунд работы... :cry:

Автор:  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/