Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: stm32 uart kline 5baud slow init
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
aneox
Для начала диалога с автомобильным эбу нужно передать 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)
    {
    }
kolobok0
Цитата(aneox @ May 14 2015, 20:46) *
Для начала диалога...


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

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

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

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

Вы спокойно выдохните воздух, возьмите на вооружение мысль что барабашки сейчас пошли спать и им стало лениво лично Вам гадить,
что про страшные закладки от буржуев знают только "спецы" на первом канале...
А всё остальное у большинства(ну если нет следа от хая в гугле какого нить косяка по теме у СТМа) радиолюбителей прекрасно(!) работает...
Посему просто тупо Ваш глаз замылился и не охватывает всего сразу - отсюда и блокируются ваш мозх sm.gif

Разбейте задачу на составные и поверьте - косяк тут-же испугается вашего тотального наступления sm.gif
такими историями нормальный радиолюбитель может тоннами заваливать внучков под старость sm.gif

aneox
Спасибо за ответ) Просто опыта не хватает, первый раз со 105м работаю, он хотел кварц 25мгц а у мну 8, получилось что проц работал 115мгц и уарт глючил. Добавил дефайн "HSE_VALUE=8000000" и все заработало на 72мгц, сразу чето не дошло, старый код от 103 взял и все. Спасибо за внимание blush.gif
kolobok0
Цитата(aneox @ May 14 2015, 21:54) *
...Спасибо за внимание...


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

чтобы получить конект с эбу, нужно сначала софтово подергать ножки, потом уже аппаратно уартом. все это работает сейчас так
Код
                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();

                //после этого получаю данные в прерывании
mr_smit
Авто какое?
aneox
Цитата(mr_smit @ May 15 2015, 04:57) *
Авто какое?


ариста, но повторюсь, на авр алгоритм работает. сейчас добавил NVIC_SystemReset(); в случае обрыва и оно как бы работает, почемуто уарт нормально запускается только после ресета(
mr_smit
В обработчике прерывания от 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... в вашем случае. Поправил.
aneox
спасибо, но на сколько я знаю, считывания байта из UART4->DR сбросит нужный флаг, в лубом случае я бы заметил повисшее прерывание, подставил вашу строчку, ничего не изменилось
mr_smit
Да, подзабыл.
Цитата
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.


Цитата(aneox @ May 15 2015, 08:11) *
добавил 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 такой финт хочу сделать, только всё руки не доходят.
aneox
отправку из прерывания убрал еще вчера, сегодня вот так пробую
Код
  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)


проверка на прерывание переполнения аппаратного буфера и сброс флага
Golikov A.
Цитата
и уже в прерывание уарт не входит

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

Вряд ли процессор перестает работать, скорее всего вы что-то выключили и забыли включить. Что вы делаете для переинита системы?
mr_smit
Цитата(Golikov A. @ May 15 2015, 13:19) *
что значит не выходит? То есть символы идут а прерывания нет? Или символы тоже не идут?

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

Цитата(aneox @ May 15 2015, 11:55) *
но если эбу выключить и включить(типо обрыв), после 5ти таймаутов о не получении код начинается сначала и уже в прерывание уарт не входит после 5бод слоу инита, тут делаю ресет nvic reset и линк поднимается


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

Включайте свою поделку одновременно с зажиганием. Я, в своё время, просто от замка зажигания запитал бортовик и всё. Включили зажигание - подключились, показали параметры. Выключили зажигание - бортовик потух. Один хрен ЭБУ выходит на связь только при включенном зажигании. К чему весь этот велосипед с "делаю ресет".
Rash
есть ещё и другая особенность, при вкл. зажигания некоторые ЭБУ отправляют посылку, при этом не смотрят занята шина или нет.
aneox
Цитата(Golikov A. @ May 15 2015, 10:19) *
что значит не выходит? То есть символы идут а прерывания нет? Или символы тоже не идут?

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

прерывание не срабатывает я имел ввиду, данные идут на линии, а прерывания нет. для переинита использую вот этот код
Код
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сек, в первых постах есть ведь код
Golikov A.
а ну все правильно написано, все должно работатьsm.gif))...

вы шутите? какая разница как вы машете ногами, гораздо важнее как вы глушите UART чтобы начать на тех же ногах махать и как вы потом его обратно заводите.
что в этих функциях
kline_Serial_End();
kline_Serial_Start();


если данные идут, а прерывания нет, то варианты 3
1. Вы не настроили входную ногу на альтернативную функцию и не подключили ее к UART (настроили не на ту функцию, или сняли подтяжку и сделали ногу опен драин и т.д.).
2. Вы сняли флаг разрешения прерывания и не поставили его обратно.
3. Вы заглушили питание модуля UART может вместе с клоками и не включили ничего обратно и не настроили заново UART.

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

я лично ставлю на то что когда вы ноги переопределяете у вас где-то стоит |= без сброса начального состояния, многие делают инициализацию исходя из того что регистры в начальном состоянии как после ресета. Потом меняют регистр в других настройках и вместо 0x00 он становится 0x04 (например), и когда они потом делают начальную настройку Reg |= 0x01; ждут что он станет 0х01, а он становиться 0х05 - а иногда это фатально.
Именно поэтому после сброса легчает, потому что регистры приводятся в исходное состояние....

И еще в HAL библиотеке постоянно проверяют состояние периферии, после глушения проверьте в структуре не ставиться ли какой-то дурной статус, при котором функции повторной инициализации вместо инициализации выйдет с ошибкой.

Ну и конечно неплохим тоном было бы собирать коды ошибок выполнения функций...
mr_smit
Цитата(aneox @ May 15 2015, 16:07) *
mr_smit стесняюсь спросить, неужели не видно задержки тут ? vTaskDelayUntil(&xLastWakeTime, 300);

Вы уже столько кода привели что в каждую строчку не вникнешь. Я говорил про саму идею реализации. Где возможны грабли. Если вы это всё уже учли, то это хорошо. Надо дальше искать.

P.S. Тем не менее не понимаю почему бы не подключить бортовик к зажиганию и не морочить дальше голову.
Golikov A.
проверяйте функции DeInit она там тактирование случаем не отключает не сбивает? Потому что небось все клоки в одном месте настраиваются в начале программы, и там небось включаются все тактирования, а если в ДеИните тактирование выключается, то до ресета ничего обратно не включится...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.