Jump to content

    
Sign in to follow this  
aneox

stm32 uart kline 5baud slow init

Recommended Posts

Для начала диалога с автомобильным эбу нужно передать 0х13 на скорости 5бод, на авр все реализовал и прекрано работает

 

Serial1.end();
  pinMode(txPin, OUTPUT);
  
  digitalWrite(txPin, HIGH);  
  delay(300);                //W5          
  digitalWrite(txPin, LOW);  //start bit
  delay(200);              
  digitalWrite(txPin, HIGH); // 1 1
  delay(400);                  
  digitalWrite(txPin, LOW); // 0 0
  delay(400);                      
  digitalWrite(txPin, HIGH); // 1
  delay(200);                          
  digitalWrite(txPin, LOW); // 0 0 0
  delay(600);                              
  digitalWrite(txPin, HIGH);  
  delay(200);               //W1                                  
  Serial1.begin(9600);

дальше все гуд

 

 

терь задача сделать на 105м стме, сил моих больше нет

 

void kline(void *pvParameters)
{
    static TickType_t xLastWakeTime;
    UNUSED(pvParameters);

    xLastWakeTime = xTaskGetTickCount();

    for(;;)
    {
        if(!ecuInit)
        {
            if (!slowInit)
            {
                kline_Serial_End();
                vTaskDelay(10);

                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 300);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 400);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 400);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 600);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);

                kline_Serial_Start();

                uint32_t timeout = 0;
                while (!slowInit)
                {
                    timeout++;
                    if (timeout >  10)//0xAfffff)
                        break;
                }
                if (!slowInit)
                {
//                    kline_Reset_Pin();
//                    kline_Serial_End();
//                    GPIO_SetBits(GPIOC, GPIO_Pin_10);
                    vTaskDelay(5000);
                    slowInit = 0;
//                  пауза и пробуем снова
                }
            }

 

void kline_Serial_End(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    USART_DeInit(UART4);
    USART_Cmd(UART4, DISABLE);
    USART_ITConfig(UART4, USART_IT_RXNE, DISABLE);

    klineRecieveIndex = 0;


}

void kline_Serial_Start(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);//UART4

    USART_DeInit(UART4);
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(UART4, &USART_InitStructure);

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    USART_Cmd(UART4, ENABLE);
    USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);
}

 

void UART4_IRQHandler()
{
    uint8_t data;
//    portBASE_TYPE xStatus;

    if((UART4->SR & USART_SR_RXNE))
    {

      data = UART4->DR;

      klineRecieveBuffer[klineRecieveIndex] = data;

      if (klineRecieveIndex > 48)
          klineRecieveIndex = 0;
      else
          klineRecieveIndex++;

      if (!slowInit)
      {
          if (data == 0x8F)
          {
              Usart_Send_symbol(0x70, KLINE_UART);
              klineRecieveIndex = 0;
          }

          if (data == 0xEC)
          {
              slowInit = 1;
              klineRecieveIndex = 0;
          }

                  if(USART_GetITStatus(UART4, USART_SR_ORE) == SET)
                  {
                       USART_ReceiveData(UART4);
                   }
}

      }

 

 

Вообщем пару раз прилетает после первой попытки FF и все, при повторных молчок. Железка точно работает, на ноги стм тыкаю авку и она успешно коннектится к эбу. Трансивер стшный 9637

 

в ответ на бит банг эбу должен отвечать 55 E9 8F , но приходит FF FF, полагаю что битбанг успешно отрабатывает, проблема в приеме

 

возможно чтото с частотами напутал, мож тут косяк подскажите

void SetSysClockTo72(void)
{
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------*/
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  if (RCC_WaitForHSEStartUp() == SUCCESS)
  {

    FLASH_SetLatency(FLASH_Latency_2);
    RCC_HCLKConfig(RCC_SYSCLK_Div1);
    RCC_PCLK2Config(RCC_HCLK_Div1);
    RCC_PCLK1Config(RCC_HCLK_Div2);

    RCC_PREDIV1Config(RCC_PREDIV1_Source_HSE, RCC_PREDIV1_Div1);
    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9);

    RCC_PLLCmd(ENABLE);

    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    while (RCC_GetSYSCLKSource() != 0x08)
    {
    }

Edited by aneox

Share this post


Link to post
Share on other sites
Для начала диалога...

 

Понимаете Вы наверное ждёте, что тут все шли именно той дорогой что идёте Вы. Что все работали с эбу, или на худой

случай в мозгах сейчас сэмулируют и проверят все временные задержки, настройки и прочие закоулки?

 

Отчасти это так конечно же...

Но вот, что тяжело тупо стэп бай стэп локализовать траблу?

 

Ну типа там сигналить на какой нить пин, глянуть осцилом, что твориться на выходах или как то разбить на составные хотя бы

общую проблему.

 

Лично мне так и не стало понятно после нескольких раз прочтения

Проблема в чём? В переключении в режим юарта или прерывание не пробегает или не получается проинициализировать порты мк???

 

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

что про страшные закладки от буржуев знают только "спецы" на первом канале...

А всё остальное у большинства(ну если нет следа от хая в гугле какого нить косяка по теме у СТМа) радиолюбителей прекрасно(!) работает...

Посему просто тупо Ваш глаз замылился и не охватывает всего сразу - отсюда и блокируются ваш мозх :)

 

Разбейте задачу на составные и поверьте - косяк тут-же испугается вашего тотального наступления :)

такими историями нормальный радиолюбитель может тоннами заваливать внучков под старость :)

 

 

Share this post


Link to post
Share on other sites

Спасибо за ответ) Просто опыта не хватает, первый раз со 105м работаю, он хотел кварц 25мгц а у мну 8, получилось что проц работал 115мгц и уарт глючил. Добавил дефайн "HSE_VALUE=8000000" и все заработало на 72мгц, сразу чето не дошло, старый код от 103 взял и все. Спасибо за внимание :blush:

Share this post


Link to post
Share on other sites

так, ну проблема всетаки есть. обясню

 

чтобы получить конект с эбу, нужно сначала софтово подергать ножки, потом уже аппаратно уартом. все это работает сейчас так

                kline_Serial_End();
                vTaskDelay(100);

                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 300);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 400);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 400);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 600);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);

                kline_Serial_Start();
//после этого получаю данные в прерывании

 

старт и енд описаны в первом посте. Все работает. Но иногда соединение рвется и нужно повторить софтовое дерганье, так вот на второй раз уже в рантайме после битбанга я в прерывание уарта не попадаю, не могу понять в чем причина. Работоспособность прерывания уарта восстанавливается только после ресета проца.

 

при первом запуске даже так работает

//                
                kline_Serial_Start();
                vTaskDelay(100);
                kline_Serial_End();
                vTaskDelay(100);
                kline_Serial_Start(); // дважды переключаю, норм.
                vTaskDelay(100);
                kline_Serial_End();
                vTaskDelay(100);
//                kline_Serial_Start();  ///а трижды уже не срабатывает прерывание
//                vTaskDelay(100);
//                kline_Serial_End();
//                vTaskDelay(100);

                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 300);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 400);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 400);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 600);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);

                kline_Serial_Start();

                //после этого получаю данные в прерывании

Edited by aneox

Share this post


Link to post
Share on other sites
Авто какое?

 

ариста, но повторюсь, на авр алгоритм работает. сейчас добавил NVIC_SystemReset(); в случае обрыва и оно как бы работает, почемуто уарт нормально запускается только после ресета(

Share this post


Link to post
Share on other sites

В обработчике прерывания от USART надо сбрасывать флаг прерывания:

void UART4_IRQHandler()
{
    uint8_t data;
//    portBASE_TYPE xStatus;

    if((UART4->SR & USART_SR_RXNE))
    {

      UART4->SR&=~USART_SR_RXNE; // сбрасываем флаг прерывания

      data = UART4->DR;

......

 

Опечатка: не USART4->SR..., а UART4->SR... в вашем случае. Поправил.

Edited by mr_smit

Share this post


Link to post
Share on other sites

спасибо, но на сколько я знаю, считывания байта из UART4->DR сбросит нужный флаг, в лубом случае я бы заметил повисшее прерывание, подставил вашу строчку, ничего не изменилось

Share this post


Link to post
Share on other sites

Да, подзабыл.

RXNE - This bit is set by hardware when the content of the RDR shift register has been transferred to

the USART_DR register. An interrupt is generated if RXNEIE=1 in the USART_CR1 register.

It is cleared by a read to the USART_DR register.

 

добавил NVIC_SystemReset(); в случае обрыва и оно как бы работает, почемуто уарт нормально запускается только после ресета(

Судя по всему то что работает это чистая случайность. Никаких обрывов быть не должно. Не знаю как там у японцев, но я когда бортовик себе под BOSCH делал - никаких обрывов не было. Связь очень стабильная. Мне кажется вы что то перемудрили с USARTом оттого и глючит.

 

Ну вот элементарно:

Usart_Send_symbol(0x70, KLINE_UART);

вставлять это в прерывании, мягко говоря, не правильно. Ни на AVR ни на STM32.

 

А это что?

void UART4_IRQHandler()
{

...

if(USART_GetITStatus(UART4, USART_SR_ORE) == SET)
{
    USART_ReceiveData(UART4);
  }
}

 

Я бы так сделал:

#define Connect      1
#define ReadData     2

int mode;

#define BUFFER_SIZE 200
unsigned char buffer[BUFFER_SIZE];                       // приемный буфер

volatile unsigned char   counter;    // счетчик принятых байт

// прерывание USART
if если байт успешно приняли
   {
   buffer[counter] = data;   // положили его в буфер
   if (++counter == BUFFER_SIZE) {
     counter = 0;
     }
   }

void main(void)
{ 
  ...
  while (1) 
  {
  switch (mode)               // смотрим в каком режиме находимся
   {                               
    case Connect:            // если только что включились => подключаемся к ЭБУ
    //
    // если всё хорошо
    //
    mode = ReadData;     // переходим в режим чтения информации

    case ReadData:
    //
    //  отправляем -> читаем
    //
  }
}
}

В прерывании USART надо только положить байт в буфер и больше ничего.

 

P.S. А вообще можно и обычный Init сделать и не заморачиваться с этим fast 5 baud. Единственное старые мозги могут его не поддерживать. Ну ооочень старые. И тогда всё сведется к тому что надо будет дрыгнуть ногой и потом отослать строчку вида 81 10 f1 81 03 на нормальной скорости 10400 и потом на ней же работать. Только адрес ЭБУ подобрать (0-255). На каком откликнется с тем и работать. Я вот с Relault Logan такой финт хочу сделать, только всё руки не доходят.

Edited by mr_smit

Share this post


Link to post
Share on other sites

отправку из прерывания убрал еще вчера, сегодня вот так пробую

  uint8_t data;

    if((UART4->SR & USART_SR_RXNE))
    {
        data = UART4->DR;

        klineRecieveBuffer[klineRecieveIndex] = data;

        if (!slowInit)
        {
            if (data == 0x8F)
            {
                check_slow_init = 1;
                klineRecieveIndex = 0;
            }

            if (data == 0xEC)
            {
                slowInit = 1;
                klineRecieveIndex = 0;
            }
            return;
        }

        if (!fastInit && slowInit)
        {
            if (data == 0xBF)
            {
                fastInit = 1;
                klineRecieveIndex = 0;
            }
            return;
        }

................

 

и все как бы работает, но если эбу выключить и включить(типо обрыв), после 5ти таймаутов о не получении код начинается сначала и уже в прерывание уарт не входит после 5бод слоу инита, тут делаю ресет nvic reset и линк поднимается

 

еслиб можно было без 5 бод слоу инита, я бы по вашему парился с ним?) тут только так у тойоты

 

а на счет перемудрить с уартом, код перед вами ведь, довольно стандартный, как там перемудрить то можно

 

а это

if(USART_GetITStatus(UART4, USART_SR_ORE) == SET)

 

проверка на прерывание переполнения аппаратного буфера и сброс флага

Share this post


Link to post
Share on other sites
и уже в прерывание уарт не входит

что значит не выходит? То есть символы идут а прерывания нет? Или символы тоже не идут?

 

Вряд ли процессор перестает работать, скорее всего вы что-то выключили и забыли включить. Что вы делаете для переинита системы?

Share this post


Link to post
Share on other sites
что значит не выходит? То есть символы идут а прерывания нет? Или символы тоже не идут?

Поддержу. Это бы желательно проверить.

 

но если эбу выключить и включить(типо обрыв), после 5ти таймаутов о не получении код начинается сначала и уже в прерывание уарт не входит после 5бод слоу инита, тут делаю ресет nvic reset и линк поднимается

 

Типо обрыв это нифига не выкл/вкл. После включения ЭБУ как минимум 300 мс "запускается". Об этом даже в протоколе говорится. Нельзя раньше 300 мс после включения ничего слать. Поэтому, возможно, вы просто не выжидаете эти 300 мс и делаете сброс, а пока инициализация STM-ки закончится, тут уже и ЭБУ просыпается. Сколько ваши "5 таймаутов" длятся?

 

Включайте свою поделку одновременно с зажиганием. Я, в своё время, просто от замка зажигания запитал бортовик и всё. Включили зажигание - подключились, показали параметры. Выключили зажигание - бортовик потух. Один хрен ЭБУ выходит на связь только при включенном зажигании. К чему весь этот велосипед с "делаю ресет".

Edited by mr_smit

Share this post


Link to post
Share on other sites
что значит не выходит? То есть символы идут а прерывания нет? Или символы тоже не идут?

 

Вряд ли процессор перестает работать, скорее всего вы что-то выключили и забыли включить. Что вы делаете для переинита системы?

прерывание не срабатывает я имел ввиду, данные идут на линии, а прерывания нет. для переинита использую вот этот код

kline_Serial_End();
                vTaskDelay(100);

                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 300);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 400);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 400);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);
                GPIO_ResetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 600);
                GPIO_SetBits(GPIOC, GPIO_Pin_10);
                vTaskDelayUntil(&xLastWakeTime, 200);

                kline_Serial_Start();

 

mr_smit стесняюсь спросить, неужели не видно задержки тут ? vTaskDelayUntil(&xLastWakeTime, 300);

 

в тех двух функциях и видны таймауты по 5сек, в первых постах есть ведь код

Edited by aneox

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this