79 lines
3.5 KiB
Markdown
79 lines
3.5 KiB
Markdown
# can-sensor
|
||
|
||
Однокадровый транспорт SETCAN SETTINGS для привязки 64-битного ROM 1-Wire к
|
||
локации «номер сборки + позиция» по шине CAN.
|
||
|
||
Ядро на C99: не включает заголовки периферии, не обращается к регистрам,
|
||
не пользуется прерываниями. Обмен идёт через таблицу `CanSensor_Io`,
|
||
которую заполняет порт платы.
|
||
|
||
Сообщение помещается в один Extended CAN-кадр: локация находится в Body
|
||
29-битного ID, а ROM — в восьми байтах payload:
|
||
|
||
```
|
||
запрос 0x17FEZZYY: DLC=0 — GET, DLC=8 — WRITE/REPLACE/CLEAR
|
||
ответ 0x1FFEZZYY: DLC=8 — текущий ROM, DLC=1 — код ошибки
|
||
```
|
||
|
||
## Состав
|
||
|
||
| Файл | Что делает | Зависимости |
|
||
|---|---|---|
|
||
| `can_sensor.h`, `can_sensor.c` | сборка и разбор SETTINGS, повторы передачи, счётчики обмена | `stdint.h` |
|
||
| `ports/stm32f1/` | опросный порт CAN1: GPIO, BTR, фильтр, mailbox/FIFO, тайм-аут ACK | CMSIS `stm32f10x.h` |
|
||
|
||
`ZZ` — номер сборки, `YY` — позиция. Нулевой ROM с DLC=8 очищает локацию.
|
||
|
||
## Что нужно от платформы
|
||
|
||
```c
|
||
uint8_t send(void *ctx, const CanSensor_Frame *frame); /* 1 — кадр принят */
|
||
uint8_t receive(void *ctx, CanSensor_Frame *frame); /* 1 — кадр получен */
|
||
```
|
||
|
||
`receive` необязателен: с нулевым полем узел работает только на передачу.
|
||
|
||
## Быстрый старт
|
||
|
||
```c
|
||
CanSensor link;
|
||
CanSensor_Io io = { .send = bxcan_send, .receive = bxcan_receive, .context = &board };
|
||
CanSensor_Config config;
|
||
CanSensor_ConfigDefault(&config); /* TX 0x1FFE0000, RX 0x17FE0000 */
|
||
|
||
CanSensor_Init(&link, &io, &config);
|
||
CanSensor_SendId(&link, position, assembly_serial, rom);
|
||
|
||
CanSensor_Message message;
|
||
if (CanSensor_Poll(&link, &message)) { /* принят идентификатор */ }
|
||
```
|
||
|
||
## Порт STM32F1
|
||
|
||
Порт не использует STM32 HAL и не занимает прерывания. Скопируйте
|
||
`ports/stm32f1/can_sensor_stm32f1_config.f103.template.h` в приложение под
|
||
именем `can_sensor_stm32f1_config.h`, добавьте `ports/stm32f1` в include path и
|
||
соберите `can_sensor_stm32f1.c` вместе с ядром:
|
||
|
||
```c
|
||
CanSensorStm32F1_Port bxcan = {0};
|
||
CanSensor_Io io;
|
||
|
||
CanSensorStm32F1_Start(&bxcan, 500000U, 0x17F00000UL, 0x1FF00000UL, 0U);
|
||
io = CanSensorStm32F1_MakeIo(&bxcan);
|
||
CanSensor_Init(&link, &io, &config);
|
||
|
||
/* Из главного цикла: */
|
||
CanSensorStm32F1_Task(&bxcan, now_ms, 20U);
|
||
```
|
||
|
||
Фильтр порта принимает только Extended data-кадры. Маска задаётся приложением:
|
||
можно пропустить только SETTINGS либо оставить открытым `MsgType` для соседних
|
||
команд того же узла. `CanSensorStm32F1_Receive()` доступна отдельно, если перед
|
||
`CanSensor_HandleFrame()` приложению нужно разобрать такие команды самому.
|
||
|
||
## Проверено в проектах
|
||
|
||
`KONOR_ds18b20` — bxCAN на STM32F103C8T6. Естественная пара — [`ds18b20`](../ds18b20):
|
||
ROM-коды, найденные `DS18B20_Search()`, уходят в шину как есть.
|