Перейти к содержанию
    

Может, ack не стирается где-то когда-то после обработки принятого?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

36 минут назад, jenya7 сказал:

но от компайлера за 5 кусков зеленых ждешь чего то большего.

Похоже, вы ожидаете от него телепатии? Как и от нас, выкладывая по капельке кусочки кода, а то и вовсе описывая его на словах. Увы, это не сработает ни в первом, ни во втором случае.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 minutes ago, Сергей Борщ said:

Похоже, вы ожидаете от него телепатии? Как и от нас, выкладывая по капельке кусочки кода, а то и вовсе описывая его на словах. Увы, это не сработает ни в первом, ни во втором случае.

Все просто. Через мастера пишу читаю параметры слейвов.

uint32_t COM_MotParam(uint32_t argc, char** args)
{
    uint8_t data[8]; 
    uint32_t mot_num = 0, size = 0, ack = 0, i;
    uint32_t timeout;
    int32_t value;
    uint8_t opcode;  
    
    mot_num  = atoi(args[1]);
        
    if ((mot_num > 0) && (mot_num < MAX_MOTORS))  
        mot_num--;
    else
       return MSG_INV_ARG; 
     
    opcode = command.var_offset;
  
    if (argc > 1) //param mot_num val
    {
        size = 2;
        value = atoi(args[2]);
        data[0] = value;
        data[1] = value>>8; 
    }
    
    //send parameter to slave
    CAN_TX(motor_rt_params[mot_num].mot_id, opcode, data, size); 
    
    timeout = TIM_GetTimeStamp_ms(TIM6) + 1000;
    
   //wait for response 
    while (1)
    {
       ack = CAN_RX_Master();
        
        if (ack == 1)
        {
            for (i = 0; i < 10000; i++) ;  //to fix the problem
            
            value = (RxMessage.Data[1] << 8) | RxMessage.Data[0];
            Parser_SendInt(COM_USART, value, 1, 0);
            break;
        }
        else
        {
            if (TIM_GetTimeStamp_ms(TIM6) > timeout)
            {
                Parser_SendString(COM_USART, "No response\n", 0);
                break;
            }
        }
    }
    
    return MSG_OK;
}

если ack = CAN_RX_Master(); вернул мне 1 - значит призошел ивент can_message_received = 1
 

uint32_t CAN_RX_Master(void)
{
    uint32_t mot_num;
    uint32_t opcode;
    uint32_t pos;  
    uint32_t ack = 0;
   
    if (can_message_received)
    {
        can_message_received = 0;

        //тут много кейсов - зашел в кейс - ack = 1
    }

    return ack;  
}

  и значит данные пришли. так с какого перепугу value = (RxMessage.Data[1] << 8) | RxMessage.Data[0]; дает мне 0?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В раздел "Предлагаю работу" лучше напишите. Хотя, в общем-то, 5 тысяч зеленых, которые Вы выложили за среду, лучше мне заплатите. Я IAR крякну, и избавлю Вас от этих злополучных проблем со средой программирования =D

 

P.S. can_message_received как объявлен?

Изменено пользователем Arlleex

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

43 minutes ago, jenya7 said:

Все просто

Это не всё! Что делаем CAN_Receive, чья это функция? Где заполняется RxMessage, где еще испольуется и как обьявен?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 minutes ago, Integro said:

Это не всё! Что делаем CAN_Receive, чья это функция? Где заполняется RxMessage, где еще испольуется и как обьявен?

я приводил уже выше

void USB_LP_CAN1_RX0_IRQHandler(void)
{
  can_message_received = 1;
 
  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это я видел, по этому и спрашиваю: Что делаем в CAN_Receive, чья это функция?

Как кстати настроен CAN?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 minutes ago, Integro said:

Это я видел, по этому и спрашиваю: Что делаем в CAN_Receive, чья это функция?

Как кстати настроен CAN?

это стандартная библиотечная функция. с КАНом проблем нет. данные приходят. если я остановлюсь дебагером в CAN_Receive я их вижу.

проблема что по флагу переменная не обновляется. if (ack == 1) { value = (RxMessage.Data[1] << 8) | RxMessage.Data[0]; }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, jenya7 said:

for (i = 0; i < 10000; i++) ; 

Вот эта вот задержка, по факту, необходима для того, чтобы "магическим" образом в RxMessage.Data появилось сообщение. Учитывая то что данные туда ложатся одним махом (а не по байтно, как я предполагал ранее), остается только три варианта:

Вариант того что приходит прерывание без данных, как пример прерывание с ошибкой или о том то фифо пусто, нужно проверять статусные флаги в обработчике
Вариант того что реально приходят два сообщения, но благодаря этой задержке, первое сообщение "теряется".
Вариант того что ack = CAN_RX_Master(); возвращает ack неверно и по совпадению каких-то обстоятельств, рашьне на пару us чем нужно :)

IAR тут точно ни при чем!))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 hours ago, Arlleex said:

Повторюсь. Флаг can_message_received как объявлен?

глобальная переменная volatile uint32_t can_message_received

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, jenya7 said:

глобальная переменная volatile uint32_t can_message_received

Ну тогда обрабатывайте все исключения и смотрите.

Я не помню зачем, но у меня в исходниках в обработчике прерывания по заполнению FIFO следующий код:

CAN_Receive(CAN1, CAN_FIFO0, &CANRxMessage);

CAN_FIFORelease(CAN1, CAN_FIFO0);

Не совсем помню, для чего нужен Release, вроде как для того, чтобы уведомить приемный автомат о том, что сообщение было обработано и нужно следующие протолкнуть по FIFO.

Изменено пользователем Arlleex

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

41 minutes ago, Arlleex said:

Ну тогда обрабатывайте все исключения и смотрите.

Я не помню зачем, но у меня в исходниках в обработчике прерывания по заполнению FIFO следующий код:


CAN_Receive(CAN1, CAN_FIFO0, &CANRxMessage);

CAN_FIFORelease(CAN1, CAN_FIFO0);

Не совсем помню, для чего нужен Release, вроде как для того, чтобы уведомить приемный автомат о том, что сообщение было обработано и нужно следующие протолкнуть по FIFO.

 

Release да нужен но он есть внутри

void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage)
{
  /* Check the parameters */
  assert_param(IS_CAN_ALL_PERIPH(CANx));
  assert_param(IS_CAN_FIFO(FIFONumber));
  /* Get the Id */
  RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RIR;
  if (RxMessage->IDE == CAN_Id_Standard)
  {
    RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 21);
  }
  else
  {
    RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 3);
  }
  
  RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONumber].RIR;
  /* Get the DLC */
  RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONumber].RDTR;
  /* Get the FMI */
  RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDTR >> 8);
  /* Get the data field */
  RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDLR;
  RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 8);
  RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 16);
  RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 24);
  RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDHR;
  RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 8);
  RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 16);
  RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 24);
  /* Release the FIFO */
  /* Release FIFO0 */
  if (FIFONumber == CAN_FIFO0)
  {
    CANx->RF0R |= CAN_RF0R_RFOM0;
  }
  /* Release FIFO1 */
  else /* FIFONumber == CAN_FIFO1 */
  {
    CANx->RF1R |= CAN_RF1R_RFOM1;
  }
}

у меня разрешено только одно прерывание - FIFO message pending Interrupt

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, jenya7 said:

у меня разрешено только одно прерывание - FIFO message pending Interrupt

Не видел, не верю!)
Гипотезу с лишним прерыванием легко проверить вставкой счетчика в обработчик.

А вообще, мне кажется, должно быть так:

void CAN1_RX0_IRQHandler(void)
{
    if (CAN_GetITStatus(CAN1,CAN_IT_FMP0)!= RESET)
    {
        CAN_ClearITPendingBit(CAN1, CAN_IT_FF0);
        CAN_ClearFlag(CAN1, CAN_FLAG_FF0);

        CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

        can_message_received = 1;
    }
} 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 hour ago, Integro said:

Не видел, не верю!)
Гипотезу с лишним прерыванием легко проверить вставкой счетчика в обработчик.

А вообще, мне кажется, должно быть так:


void CAN1_RX0_IRQHandler(void)
{
    if (CAN_GetITStatus(CAN1,CAN_IT_FMP0)!= RESET)
    {
        CAN_ClearITPendingBit(CAN1, CAN_IT_FF0);
        CAN_ClearFlag(CAN1, CAN_FLAG_FF0);

        CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

        can_message_received = 1;
    }
} 

 

спасибо. проверю.

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...