Вот и настало время, когда обсохло молоко на губах и перестали течь сопли из носа, накопил немного опыта, которым могу теперь поделиться с другими подготовленными начинающими .
Т.к. урок(и) будут рассчитан для начинающих, то и вестись они будут на связке CubeMX + Keil с использованием "могучей" библиотеки HAL (знающие поймут почему в кавычках), в связи с чем очень прошу не разводить полемику по поводу пристрастий к отдельным CMSIS, HAL, SPL, ни под каким соусом.
В качестве подопытного я решил использовать STM32F042K6T6

в семи известном и любимом корпусе ATMEGA8 (LQFP32), периферию можно посмотреть в кубе. Почему именно он? Во первых он у меня есть, во вторых Keil для него абсолютно бесплатный без каких либо ограничений, в третьих HAL дает возможность перенести код на другой камень без особых проблем (и мозги заодно потренировать в процессе, в виде закрепления материала)
Собственно приступим к самому уроку.
Запускаем куб, выбираем новый проект и камень. Включаем RCC(тактирование от внешнего кварца), SYS (активируем ноги для программирования ST-Link V2), CAN и две ножки на выход что б можно было поморгать диодиками и самое главное потом ногу PB8 посадить на землю иначе МК будет в режиме bootloader HAL про эту ногу позабыл))).

Настраиваем тактирование:

Следующая вкладка Configuration
Проверяем режим GPIO для диодиков, все по Default:

и ползем в настройка CAN:

Строчка Time for one bit имеет прямое отношение к скорости передачи CAN Kbit/s, стандартные скорости:
1000, 500, 250, 125, 100, 83.3, 50, 20, 10 Kbit/s
Моя формула для расчета скорости Time for one bit(ns)=1000000/X
где X скорость в Kbit/s, вот под расчетную скорость и начинаем просчитывать Prescaler, Time Quanta in Bit Segment 1 и Time Quanta in Bit Segment 2
А теперь самое интересное, как все это дело правильно посчитать, все дело в квантах)))
P.S. сам я не особо во все это въехал, но все же расскажу со своей колокольни.
Строчка Time Quantum показывает длину одного кванта она зависит только от делителя.
Вот нашел картинку про кванты:

по картинке мы имеем:
Sync_Seg содержит только 1tq
Prop_Seg + Phase_Seg1 может содержать 1-16tq, строчка в коде hcan.Init.BS1 = CAN_BS1_5TQ;
Phase_Seg2 может содержать 1-8tq, строчка в коде hcan.Init.BS2 = CAN_BS2_2TQ;
По картинке имеем 8 квантов, 1 квант на синхронизацию, 5 на первую фазу и 2 на вторую, для скорости 500Kbit/s (2000ns) Time Quantum=2000/8=250ns, т.е. Prescaler нужно подобрать такой, что бы Time Quantum был равен 250ns.
На что влияет соотношение BS1 к BS2 я так и не смог осознать или понять))), в разных источниках по разному, но по факту выходит, что BS1 должен быть больше BS2 или
как в другом источнике BS1=~(87,5%(BS1+BS2)), мне встречалось следующее BS1/BS2
4/3, 13/2, 6/5, и даже 6/8, 5/6 что как мне показалось не есть правильно, но хз…
P.S. в процессе написания пришлось немного разобраться в этих квантах)))
Если кто то знает больше, пишите, добавлю в статью)))
Продолжим, в самой нижней строчке режим работы
Normal — и прием и передача
LoopBack — передача и слушает сам себя
Silent — только прием и слушает сам себя
Silent+ LoopBack — полностью отключен от внешнего мира)))
Мы выбираем режим Normal.
И чуть не забыл вкладка NVIC Settings поставить галку на против CAN:

Переходим в Project->Settings и придумываем название проекту, место для хранения и для какой IDE собрать проект (MDK-ARM V5) и последний шаг Project->Generate Code

Открываем проект в Keil и сразу жмакаем на собрать проект (кнопка F7) что бы появились все связи.
Пропишем структуры приема и передачи:
/* Private variables ---------------------------------------------------------*/
static CanTxMsgTypeDef canTxMessage;
static CanRxMsgTypeDef canRxMessage;
определим нашу рукописную функцию передачи
и несколько переменных для приема:
/* Private function prototypes -----------------------------------------------*/
void CAN_Transmit(void);
/* USER CODE END PFP */
/* USER CODE BEGIN 0 */
uint16_t CAN_ID;
uint8_t CAN_DLC;
uint8_t DATA[8];
сама функция передачи:
void CAN_Transmit(void)
{
hcan.pTxMsg->StdId = 0x222;
hcan.pTxMsg->DLC = 8;
hcan.pTxMsg->Data[0] = 1;
hcan.pTxMsg->Data[1] = 2;
hcan.pTxMsg->Data[2] = 3;
hcan.pTxMsg->Data[3] = 4;
hcan.pTxMsg->Data[4] = 5;
hcan.pTxMsg->Data[5] = 6;
hcan.pTxMsg->Data[6] = 7;
hcan.pTxMsg->Data[7] = 8;
HAL_CAN_Transmit(&hcan, 10);
}

и функцию обработчика прерывания по приему с моргающим диодом на ноге PB3 сигнализирующем о удачном принятии посылки:
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
CAN_ID = CanHandle->pRxMsg->StdId;
CAN_DLC = CanHandle->pRxMsg->DLC;
DATA[0] = CanHandle->pRxMsg->Data[0];
DATA[1] = CanHandle->pRxMsg->Data[1];
DATA[2] = CanHandle->pRxMsg->Data[2];
DATA[3] = CanHandle->pRxMsg->Data[3];
DATA[4] = CanHandle->pRxMsg->Data[4];
DATA[5] = CanHandle->pRxMsg->Data[5];
DATA[6] = CanHandle->pRxMsg->Data[6];
DATA[7] = CanHandle->pRxMsg->Data[7];
HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);
}

Не забываем про структуры и настраиваем CAN фильтры в режиме IDLIST(перечисляем нужные нам ID), т.к. регистры 16 бит а ID посылки 11 бит и передача организована со старшего бита, то приходится ID двигать влево на 5 бит, не я так придумал)))
Через наш фильтр проскочат только:
0x53A, 0x53D, 0x54D, 0x54F, 0xA, 0x33, 0x44, 0x55, на остальные ID МК ни как не среагирует.
/* USER CODE BEGIN 2 */
hcan.pTxMsg = &canTxMessage;
hcan.pRxMsg = &canRxMessage;
CAN_FilterConfTypeDef canFilterConfig;
canFilterConfig.FilterNumber = 0;
canFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;
canFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
canFilterConfig.FilterIdHigh = 0x53A<<5;
canFilterConfig.FilterIdLow = 0x53D<<5;
canFilterConfig.FilterMaskIdHigh = 0x54D<<5;
canFilterConfig.FilterMaskIdLow = 0x54F<<5;
canFilterConfig.FilterFIFOAssignment = 0;
canFilterConfig.FilterActivation = ENABLE;
canFilterConfig.BankNumber = 1;
HAL_CAN_ConfigFilter(&hcan, &canFilterConfig);
canFilterConfig.FilterNumber = 1;
canFilterConfig.FilterIdHigh = 0xA<<5;
canFilterConfig.FilterIdLow = 0x33<<5;
canFilterConfig.FilterMaskIdHigh = 0x44<<5;
canFilterConfig.FilterMaskIdLow = 0x55<<5;
HAL_CAN_ConfigFilter(&hcan, &canFilterConfig);
HAL_CAN_Receive_IT(&hcan, CAN_FIFO0) ;
/* USER CODE END 2 */

Ну и в главном цикле моргаем диодом на ноге PA15 и шлем сообщение в CAN каждые 200мсек
CAN_Transmit();
HAL_Delay(200);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_15);

Финальная проверка на CAN Hacker, при отправке ID прописанными в фильтре, диодик весело моргает.

готовый проект googl диск
про отладочную плату
Продолжение

Комментарии 95
Что это? И зачем это?
HAL сильно обновился и этот код уже работать не будет, в частности сильно изменилась функция приема — передачи
Где можно почитать, а то у меня затуп с приемом сообщений
Жаль, раньше не наткнулся, все пришлось самому раскапыввать) В итоге запустил CAN, но только для 500kbps. Но также надо запустить и второй CAN, 125kbps (проц STM32F105), и вот он молчит, собака, даже в функцию обработки прерывания по приему не заходит.
Настроено так, в соответствии с калькулятором:
шина APB1 36Mhz
hcan2.Init.Prescaler = 16;
hcan2.Init.SJW = CAN_SJW_1TQ;
hcan2.Init.BS1 = CAN_BS1_12TQ;
hcan2.Init.BS2 = CAN_BS2_5TQ;
т.е.
Time for one Bit = 8000ns
Time Quantum = 444.(4)ns
Куда можно копнуть?
какой режим выставлен?
И точно ли PLL запускается на нужной частоте?
режим Normal, для обоих канов. PLL разный для них? потому что CAN1 прекрасно работает… проблема именно с CAN2
civil-zz
Жаль, раньше не наткнулся, все пришлось самому раскапыввать) В итоге запустил CAN, но только для 500kbps. Но также надо запустить и второй CAN, 125kbps (проц STM32F105), и вот он молчит, собака, даже в функцию обработки прерывания по приему не заходит.
Настроено так, в соответствии с калькулятором:
шина APB1 36Mhz
hcan2.Init.Prescaler = 16;
hcan2.Init.SJW = CAN_SJW_1TQ;
hcan2.Init.BS1 = CAN_BS1_12TQ;
hcan2.Init.BS2 = CAN_BS2_5TQ;
т.е.
Time for one Bit = 8000ns
Time Quantum = 444.(4)ns
Куда можно копнуть?
О, я щас прям с тем же 105-ым ковыряюсь. Отправлять могу с обоих, приём молчит на обоих… Пока ещё поковыряюсь, но чувствую надо мне будет кого-то потыкать палочкой.
я вроде разобрался) 105 проц кастрированный, у него одно адресное пространство для фильтров на оба кана. у меня заработало лишь при инициализации фильтров в таком виде —
для сбора всего трафика по обоим канам:
// фильтр 1 для CAN1
can1FilterConfig.FilterNumber = 0; // Номер фильтра, доступны с 0 по 13
can1FilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // Режим работы фильтра — ID+Mask
can1FilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // Разрядность (масштабирование) 32 bit
can1FilterConfig.FilterIdHigh = 0x000 << 5; // Старшая часть ID
can1FilterConfig.FilterIdLow = 0x000 << 5; // Младшая часть ID
can1FilterConfig.FilterMaskIdHigh = 0x000 << 5; // Старшая часть Mask
can1FilterConfig.FilterMaskIdLow = 0x000 << 5; // Младшая часть Mask
can1FilterConfig.FilterFIFOAssignment = CAN_FIFO0; // Номер буфера FIFO (у нас их всего два)
can1FilterConfig.FilterActivation = ENABLE; // Фильтр активен
can1FilterConfig.BankNumber = 0;
HAL_CAN_ConfigFilter(&hcan1, &can1FilterConfig); // Применяем фильтр (всегда для hcan1)
Для фильтра по ID
// фильтр 1 для CAN1
can1FilterConfig.FilterNumber = 0; // Номер фильтра, доступны с 0 по 13
can1FilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; // Режим работы фильтра — список ID
can1FilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // Разрядность (масштабирование) 16bit
can1FilterConfig.FilterIdHigh = 0x150 << 5; // ID #1
can1FilterConfig.FilterIdLow = 0x290 << 5; // ID #2
can1FilterConfig.FilterMaskIdHigh = 0x000 << 5; // ID #3
can1FilterConfig.FilterMaskIdLow = 0x000 << 5; // ID #4
can1FilterConfig.FilterFIFOAssignment = CAN_FIFO0; // Номер буфера FIFO (у нас их всего два)
can1FilterConfig.FilterActivation = ENABLE; // Фильтр активен
can1FilterConfig.BankNumber = 0;
HAL_CAN_ConfigFilter(&hcan1, &can1FilterConfig); // Применяем фильтр (всегда для hcan1)
Можно пытаться делать фильтр для второго кана, играться с номерами фильтров и номерами банков, но в случае со 105 это работать не будет — все фильтра применяются для обоих канов, независиомо от того, куда они применены. например, такая конструкция
// фильтр 1 для CAN1
can1FilterConfig.FilterNumber = 0; // Номер фильтра, доступны с 0 по 13
can1FilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; // Режим работы фильтра — список ID
can1FilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // Разрядность (масштабирование) 16bit
can1FilterConfig.FilterIdHigh = 0x150 << 5; // ID #1
can1FilterConfig.FilterIdLow = 0x290 << 5; // ID #2
can1FilterConfig.FilterMaskIdHigh = 0x000 << 5; // ID #3
can1FilterConfig.FilterMaskIdLow = 0x000 << 5; // ID #4
can1FilterConfig.FilterFIFOAssignment = CAN_FIFO0; // Номер буфера FIFO (у нас их всего два)
can1FilterConfig.FilterActivation = ENABLE; // Фильтр активен
can1FilterConfig.BankNumber = 0;
HAL_CAN_ConfigFilter(&hcan1, &can1FilterConfig); // Применяем фильтр (всегда для hcan1)
// фильтр 1 для CAN2
can2FilterConfig.FilterNumber = 14; // Номер фильтра, доступны с 14 по 27
can2FilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; // Режим работы фильтра — список ID
can2FilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // Разрядность (масштабирование) 16bit
can2FilterConfig.FilterIdHigh = 0x020 << 5; // ID #1
can2FilterConfig.FilterIdLow = 0x110 << 5; // ID #2
can2FilterConfig.FilterMaskIdHigh = 0x360 << 5; // ID #3
can2FilterConfig.FilterMaskIdLow = 0x000 << 5; // ID #4
can2FilterConfig.FilterFIFOAssignment = CAN_FIFO0; // Номер буфера FIFO (у нас их всего два)
can2FilterConfig.FilterActivation = ENABLE; // Фильтр активен
can2FilterConfig.BankNumber = 14; // Номера фильтров для CAN2 начинаются с 14
HAL_CAN_ConfigFilter(&hcan1, &can2FilterConfig); // Применяем фильтр (всегда для hcan1)
будет фильровать все перечисленные ID для обоих канов.
А мне как раз фильтр-то и не нужен, нужно принимать все с одного и отправлять на другой. И обратно. За редким исключением в виде изменения пары команд. Без фильтров вообще оно же должно работать?
Неа, фильтр должен быть обязательно. нет фильтра — нет приема.
Опа, а у меня их как раз и нет. Почему-то CubeMX не генерирует их инициализацию вовсе.
Пожалуй, проверю на досуге с ними, спасибо большое!
Конечно, не генерирует, это надо самому делать.
MrPerfekt
Опа, а у меня их как раз и нет. Почему-то CubeMX не генерирует их инициализацию вовсе.
Пожалуй, проверю на досуге с ними, спасибо большое!
Он же не знает, какие именно фильтры нужны…
Ну, саму шину он настраивать умеет. А по фильтрам как-то я не нашёл вкладок, что как бы странно. То есть если уж генерируете весь код, так давайте до конца генерировать)
Я находил некоторые примеры кода в гугле и там инициализация фильтров была. Причем с характерным сгенерированным комментарием, который был у всех одинаков.
наверно, код скопипащен друг у друга, вот и одинаковые комментарии) по факту куб фильтры не генерит, инфа 146%
Да тоже не исключено, конечно. А то, что не генерит, я вижу :)
civil-zz
я вроде разобрался) 105 проц кастрированный, у него одно адресное пространство для фильтров на оба кана. у меня заработало лишь при инициализации фильтров в таком виде —
для сбора всего трафика по обоим канам:
// фильтр 1 для CAN1
can1FilterConfig.FilterNumber = 0; // Номер фильтра, доступны с 0 по 13
can1FilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; // Режим работы фильтра — ID+Mask
can1FilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; // Разрядность (масштабирование) 32 bit
can1FilterConfig.FilterIdHigh = 0x000 << 5; // Старшая часть ID
can1FilterConfig.FilterIdLow = 0x000 << 5; // Младшая часть ID
can1FilterConfig.FilterMaskIdHigh = 0x000 << 5; // Старшая часть Mask
can1FilterConfig.FilterMaskIdLow = 0x000 << 5; // Младшая часть Mask
can1FilterConfig.FilterFIFOAssignment = CAN_FIFO0; // Номер буфера FIFO (у нас их всего два)
can1FilterConfig.FilterActivation = ENABLE; // Фильтр активен
can1FilterConfig.BankNumber = 0;
HAL_CAN_ConfigFilter(&hcan1, &can1FilterConfig); // Применяем фильтр (всегда для hcan1)
Для фильтра по ID
// фильтр 1 для CAN1
can1FilterConfig.FilterNumber = 0; // Номер фильтра, доступны с 0 по 13
can1FilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; // Режим работы фильтра — список ID
can1FilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // Разрядность (масштабирование) 16bit
can1FilterConfig.FilterIdHigh = 0x150 << 5; // ID #1
can1FilterConfig.FilterIdLow = 0x290 << 5; // ID #2
can1FilterConfig.FilterMaskIdHigh = 0x000 << 5; // ID #3
can1FilterConfig.FilterMaskIdLow = 0x000 << 5; // ID #4
can1FilterConfig.FilterFIFOAssignment = CAN_FIFO0; // Номер буфера FIFO (у нас их всего два)
can1FilterConfig.FilterActivation = ENABLE; // Фильтр активен
can1FilterConfig.BankNumber = 0;
HAL_CAN_ConfigFilter(&hcan1, &can1FilterConfig); // Применяем фильтр (всегда для hcan1)
Можно пытаться делать фильтр для второго кана, играться с номерами фильтров и номерами банков, но в случае со 105 это работать не будет — все фильтра применяются для обоих канов, независиомо от того, куда они применены. например, такая конструкция
// фильтр 1 для CAN1
can1FilterConfig.FilterNumber = 0; // Номер фильтра, доступны с 0 по 13
can1FilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; // Режим работы фильтра — список ID
can1FilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // Разрядность (масштабирование) 16bit
can1FilterConfig.FilterIdHigh = 0x150 << 5; // ID #1
can1FilterConfig.FilterIdLow = 0x290 << 5; // ID #2
can1FilterConfig.FilterMaskIdHigh = 0x000 << 5; // ID #3
can1FilterConfig.FilterMaskIdLow = 0x000 << 5; // ID #4
can1FilterConfig.FilterFIFOAssignment = CAN_FIFO0; // Номер буфера FIFO (у нас их всего два)
can1FilterConfig.FilterActivation = ENABLE; // Фильтр активен
can1FilterConfig.BankNumber = 0;
HAL_CAN_ConfigFilter(&hcan1, &can1FilterConfig); // Применяем фильтр (всегда для hcan1)
// фильтр 1 для CAN2
can2FilterConfig.FilterNumber = 14; // Номер фильтра, доступны с 14 по 27
can2FilterConfig.FilterMode = CAN_FILTERMODE_IDLIST; // Режим работы фильтра — список ID
can2FilterConfig.FilterScale = CAN_FILTERSCALE_16BIT; // Разрядность (масштабирование) 16bit
can2FilterConfig.FilterIdHigh = 0x020 << 5; // ID #1
can2FilterConfig.FilterIdLow = 0x110 << 5; // ID #2
can2FilterConfig.FilterMaskIdHigh = 0x360 << 5; // ID #3
can2FilterConfig.FilterMaskIdLow = 0x000 << 5; // ID #4
can2FilterConfig.FilterFIFOAssignment = CAN_FIFO0; // Номер буфера FIFO (у нас их всего два)
can2FilterConfig.FilterActivation = ENABLE; // Фильтр активен
can2FilterConfig.BankNumber = 14; // Номера фильтров для CAN2 начинаются с 14
HAL_CAN_ConfigFilter(&hcan1, &can2FilterConfig); // Применяем фильтр (всегда для hcan1)
будет фильровать все перечисленные ID для обоих канов.
А я не очень понял, почему оба фильтр вешаются на первый кан и почему буфер один и тот же…
ну вот так архитектура проца устроена неудачно…
community.st.com/thread/4…an2-interrupt-not-working
community.st.com/thread/4…eceive-on-slave-can-issue
на самом деле неважно, можно писать и
HAL_CAN_ConfigFilter(&hcan2, &can2FilterConfig);
все равно все фильтры к обоим канам применяются.
А кстати прерывания на что именно ставить нужно?
Я еще пока не дошел до установки прерываний самому :) Сейчас использую готовый халовский обработчик HAL_CAN_RxCpltCallback
Я про те, что в конфигурации CAN в кубе. Тут в статье просто типа поставьте галочку, а у 105-го их там вагон разных
так какие нужно, такие и ставь. Если нужно прерывание по приему, то RX0, если по передаче, то TX0. RX1 — это, насколько я понимаю, прерывание по FIFO1, которое вряд ли когда будет использоваться. SCE — не знаю, что это такое…
А, ну да, но как-то из-за отсутствия приёма ничего и не происходило) Надо пожалуй щас ковырнуть ещё разок это всё действо
civil-zz
так какие нужно, такие и ставь. Если нужно прерывание по приему, то RX0, если по передаче, то TX0. RX1 — это, насколько я понимаю, прерывание по FIFO1, которое вряд ли когда будет использоваться. SCE — не знаю, что это такое…
Поковырял, поставил фильтры одинаковые (копипаста из коммента выше), без фильтрации по факту. Ничего не изменилось, статус по приёму возвращает таймаутом и всё на этом.
civil-zz
так какие нужно, такие и ставь. Если нужно прерывание по приему, то RX0, если по передаче, то TX0. RX1 — это, насколько я понимаю, прерывание по FIFO1, которое вряд ли когда будет использоваться. SCE — не знаю, что это такое…
Кажется удалось завести CAN1 пока. Оказывается надо не только фильтр, но и RxMessage навесить на него. Я даже не знаю, как так можно криво делать. Сейчас и с CAN2 поковыряюсь, буду бросаться стаффом между ними.
Получилось?
Это давно уж решил
"очень прошу не разводить полемику по поводу пристрастий к отдельным CMSIS" — блин, а так хотелось чего нибудь ляпнуть))
Спасибо! После копипаста и маленькой правки заработало на дискавери 32f407. Не подскажете как передавать разные данные и разной длинны? Как их, к примеру, из массива доставать и куда вставлять?
так в коде все есть и прием и передача
С помощью чего был запущен CAN Hacker? Самодельная плата или покупной блок? Очень хочу найти блок для изготовления дома.
самодельная
Есть ссылка на схему?
ссылки нет, но тут была, в поиске вбей
Да уж, кейл с кубом сложновато воспринять. Потом выучу может. А пока стартовал на stm32duino. Кому интересно, смотрите в моих записях. Все элементы с Али экспресс, пайка на уровне школьника. Собираюсь написать статью по быстрому старту.
Тоже изучаю STM и 32 и 8… Очень полезная статья. Однозначно в закладки. Спасибо за проделанную работу. В квартире делал ремонт и поменял всю проводку с алюмишки на медь, заодно пробросил по всей квартире ПУГНП2х0.5 -до каждой розетки-выключателя-люстры-лампы и т.д. Как раз для шины CAN.
Да и в своей машинке всю проводку меняю и посадил на шину I2C. Буду менять на CAN, так как I2C слишком тормозная. В машине тоже использую STM32F429ZIT6U-Discko + в каждой двери-капоте-багажнике по одной STM32F042K6 с силовыми ключами на драйверах верхнего уровня+полевики.
И что все накинулись.
CAN лишь немногим сложнее SPI.
Скачиваете предложенный готовый проект, и медитируете над ним недельку.
А когда все структуры и переменные будут выжжены в мозгу как — Отче наш…
тогда и придет понимание истины.
А можно взять готовые примеры из того же HAL, SPL… и помедетировать над ними…
…гы… я день медитировал, байты куда то полетели, принять не получилось… может фильтра не так настроил… сам на себя контроллер и отправлял и принимал. А вот другой платой принять не смог. Может с частотами еще напутал.
На тот момент серия проблем нарисовалась, пришлось отложить на какое то время. Но вечером может ещё посмотрю. Интересно все же.
все получиться!
kostya261
И что все накинулись.
CAN лишь немногим сложнее SPI.
Скачиваете предложенный готовый проект, и медитируете над ним недельку.
А когда все структуры и переменные будут выжжены в мозгу как — Отче наш…
тогда и придет понимание истины.
А можно взять готовые примеры из того же HAL, SPL… и помедетировать над ними…
…гы… я день медитировал, байты куда то полетели, принять не получилось… может фильтра не так настроил… сам на себя контроллер и отправлял и принимал. А вот другой платой принять не смог. Может с частотами еще напутал.
На тот момент серия проблем нарисовалась, пришлось отложить на какое то время. Но вечером может ещё посмотрю. Интересно все же.
Вот и у меня тоже, вылетать вылетают и ловятся другими девайсами, а на приёме тишина. Колдовать дальше надо, видимо.
под кондрашова копаеш ?)
А с кем Вы сейчас разговаривали? :(
Меня всегда забавляют этакие критики — " Соседовы " . Сами ничего из себя не представляют, знаний не больше чем у моего таракана, который живет под холодильником, но зато хлебом не корми, дай поумничать )))
Там после CubeMX остается память на что-то полезное? ))
Остается очень много
Я тут маленько покопался перечитывая, заинтересовала иллюстрация с фотонами: Судя по схеме( не скрою, погуглил:): для синхронизации имеется один фотон, один фотон для компенсации физических задержек сигнала в сети, четыре фотона используются для компенсации фазовой ошибки фронта сигнала. Может быть удлинен при ресинхронизации по отношению к двум фотонам PHASE_SEG2. Возник вопрос: как работают в купе эти пять фотонов с разноименными задачами.
Квант это неделимая порция вещества, энергии, момента или другой величины вообще, а фотон это квант одного конкретного электромагнитного излучения. Частный случай. Один из множества.
Спасибо! В закладки закину, может пригодится попозже! :)
Про ногу BOOT забыл, к земле прижать ))
Да точно!
а не подскажите, на базе ардуино нано и блока mcp2515 тоже можно собрать такое ?
А какое отношение имеет авр к стм?
просто я в этом не разбираюсь :( по этому и спрашиваю
Ааа, ну тут надо скиллы прокачивать)))
urabus87
а не подскажите, на базе ардуино нано и блока mcp2515 тоже можно собрать такое ?
можно, но танцы еще те, там и кварц менять на китайском mcp, и смотря какую шину слушать будете
www.drive2.ru/l/470201750645637625/ собрал в вот таком виде, скинули програмку для прослушки, залил ее в ардуину, подключил к машине рено сандеро, и через серийный порт в программе ардуино смотрел бегущие данные, скопировал в блокнот от туда в эксель и выбирал от туда уже повторяющиеся
ut2k5
можно, но танцы еще те, там и кварц менять на китайском mcp, и смотря какую шину слушать будете
никаких танцев. есть библиотеки для 8 МГц кварца, а для шины только скорость выбрать программно. всё заводится с пол тычка.
так поделитесь опытом, жаждем
www.drive2.ru/l/460733581140951184/ конечный вариант в процессе
спасибо
Ничего не понятно, но думаю очень полезная информация.
Это все здорово, конечно. Но, простите, а что за прибор вы мастерите?
Хорошая статья. Но, есть одно НО. В HAL есть куча своих косяком. Например в модуле RTC. Работая в такой концепции: куб_проект_вставили где надо и побежали, можно много упустить, и потом потратить кучу времени, выискивая злостный глюк.
Я пользуюсь кубом только для пинов, и подсмотреть примеры в репозитории. В остальном, он очень избыточен, и очень сильно раздувает проект.
А за статью большой +.
Я сам не сторонник хала, но приходиться и на нем работать
Прям тоже на все 100 согласен. Увы, глюков в нем не поубавилось.
Кстати, я использую SystemWorkbench 32 for stm32 — она полностью бесплатная, довольно развитое сообщество, нет ограничения по коду и есть возможность создания пустых проектов. И Куб его поддерживает.
без глюков жизнь покажется скучной)))
Я свои глюки люблю. Мне их хватает. А вот чужие глюки вылавливать… на это уже тратить жизнь не хочется . :-)
Этож какой моск надо иметь жаропрочный. Мой закипел))))) Ни хрена не понял)))))
надо созреть для CAN)))
Да вот зрею-зрею… То ли солнца мало, то ли водой плохо поливают)))
Здесь не водой, а пол литрой поливать нужно, чтобы процесс созревания пошел…
Дык не действует зелье это, только мозг в защиту уходит. А тема интересная, тока времени ее жевать немного, вот и не идет процесс созревания(((
Вот же круто… А зачем? (С)
В общих чертах ясно, но ты расскажи, для чего это? Собственный сканер типа ELM делать?
цели у всех разные…
UncleGreg
Вот же круто… А зачем? (С)
В общих чертах ясно, но ты расскажи, для чего это? Собственный сканер типа ELM делать?
Не обязательно. CAN универсальная шина. Можно и просто свою сеть устойчивую к помехам организовать. Да ту же систему умный дом, забабахать можно. Не обязательно зацикливаться на авто :)
А, точно, это уже профдеформация :)
Понял не все, по этому утащил в закладки, надо будет быстро найду. Учебники предназначены для непонимающих, а понимающие пишут их. Спасибо, желаю всем делится знаниями
Это все конечно хорошо, но очень запутано. Использованы сленги, не всегда адекватно воспринимаемые новичками. Плюс терминология структуры сообщения сети не классическая. Вообщем явно не урок для начинающих
Ну… может новичкам стоит начать со светодиодов и кнопочек. Да и мк для старта выбрать попроще?
Я не наезжаю, просто с stm32 для старта сразу много вводной информации. Может сбить с толку и в конец запутать.
Поскольку там даже что бы помигать светодиодом на пине, нужно заполнить несколько структур… типа конфигурации выводов (направление, к чему подтянуты, если подтянуты, на какой частоте и т.д.), конфигурация генератора… в общем много. В сравнении с теми же avr или pic, где ddr( или tris в мк pic) конфигурирует направление работы вывода, а регистром port либо опрашиваешь, либо выставляешь значение. Ну это в двух словах…
Вот структуры и сбивают с толку новичков, переезжающих с авров и пиков. Юзайте референс мануал и пишите прямо в регистры без SPL/HAL и переезд пройдет гораздо проще и безболезненней.
Да чего уж там…
Ассемблер и только он!
Только тогда придет истинное понимание работы микроконтроллера и его переферии :)
И ни каких именованных регистров, лишь численное представление таковых. За одно и скилл памяти прокачаем :)
А что бы и с ассемблером не заморачиваться, программу можно написать на листочке, к каждой команде подставить ее числовой эквивалент и затем с помощью hex редактора, вручную записать в бинарник. А то размякли тут все со своими ардуинами (иде) и кейлами с иарами…
PS это я так не к месту шутю…
А вообще я даже и не программист. Водитель я…
Ну вот, теперь все понятно:)))
И тут я понял, что я профан(((
Спасибо, но учитель из вас никакой. Вы я так понял рассказали знающим о том что вы знаете, а не начинающим…
Для понятия моих слов я вам приведу пример как я пишу инструкции по эксплуатации… Сажусь за ноут, представляю что передомной сидит женщина лет 60, блондинка, плохо знающая русский… Мне надо объяснить ей как надо работать, при этом надо что бы она поняла как это работает… И начинаю подробное описание с выделение рабочих процессов для понимания ситуации процесса в производстве… Проще говоря описываю ее действия, сам процесс внутри станка, узлов и механизмов затрагивающие процесс выполнения и почему они так называются… 😁
ПЫ.СЫ. честно прочитал всю статью, но понял только самое начало… 😁 Не будете ли вы столь любезны описать подробно сие действие с максимум пояснениями? ☺
Поддерживаю. Статья не для начинающих.
floirizel
Спасибо, но учитель из вас никакой. Вы я так понял рассказали знающим о том что вы знаете, а не начинающим…
Для понятия моих слов я вам приведу пример как я пишу инструкции по эксплуатации… Сажусь за ноут, представляю что передомной сидит женщина лет 60, блондинка, плохо знающая русский… Мне надо объяснить ей как надо работать, при этом надо что бы она поняла как это работает… И начинаю подробное описание с выделение рабочих процессов для понимания ситуации процесса в производстве… Проще говоря описываю ее действия, сам процесс внутри станка, узлов и механизмов затрагивающие процесс выполнения и почему они так называются… 😁
ПЫ.СЫ. честно прочитал всю статью, но понял только самое начало… 😁 Не будете ли вы столь любезны описать подробно сие действие с максимум пояснениями? ☺
ну уж что есть, CAN это не диодиками моргать, пусть будет статья для новичков продвинутых))))
И все же. Может попробуешь разложить по полочкам? Уверен, все получится! 😁
floirizel
Спасибо, но учитель из вас никакой. Вы я так понял рассказали знающим о том что вы знаете, а не начинающим…
Для понятия моих слов я вам приведу пример как я пишу инструкции по эксплуатации… Сажусь за ноут, представляю что передомной сидит женщина лет 60, блондинка, плохо знающая русский… Мне надо объяснить ей как надо работать, при этом надо что бы она поняла как это работает… И начинаю подробное описание с выделение рабочих процессов для понимания ситуации процесса в производстве… Проще говоря описываю ее действия, сам процесс внутри станка, узлов и механизмов затрагивающие процесс выполнения и почему они так называются… 😁
ПЫ.СЫ. честно прочитал всю статью, но понял только самое начало… 😁 Не будете ли вы столь любезны описать подробно сие действие с максимум пояснениями? ☺
Статья лично мне замечательно помогла в настройке моего барахла, но я уже немного освоил азбуку ранее. Для тех, кто и азбуку в руках не держал, эта статья конечно бесполезна.
Ничего не понял, но здорово, молодец.
Если эту информацию параллельно выложить на радиофорумах (типа радиокот, паяльник…) Наверняка появятся комментарии от специалистов по АРМам.
А так интересно, для меня КАН шина вообще темный лес.
В шинах, как правило, ничего сложного нет. Их для этого умные дядьки и разрабатывают с оглядкой на наиболее компактную и дешевую реализацию в кристалле.
Сложны протоколы обмена, неважно на какой шине они реализованы.
Отлично!
Надо во всё это въехать, но страшно, ппц
неужели так все страшно я расписал? я инфу по крупицам собирал долгое время.
нет нестрашно… просто тут не все программисты…)))))
— Папа, а почему, когда яблоко откусишь, оно делается коричневым?
— Дело в том, сынок, что в яблоке имеются различные химические вещества. Одно из них — железо. Так вот, когда железо вступает с кислородом, находящимся в воздухе, в химическую реакцию, получается окисление. В результате образуется вещество, которое и окрашивает яблоко в коричневый цвет.
— Папа, а с кем ты сейчас разговаривал?
Аааа! 😁 Порвало! 😁 Прям в точку! 😁