🚗 hal::can
Controller Area Network - Automotive Communication
383 satır
~14 fonksiyon
Automotive
📖 Genel Bakış
CAN (Controller Area Network) otomotiv ve endüstriyel uygulamalarda kullanılan güvenilir haberleşme protokolüdür. ECU (Engine Control Unit), sensörler ve aktüatörler arası iletişim sağlar.
🔑 Temel Özellikler
- CAN 2.0A (11-bit ID) / 2.0B (29-bit ID)
- Up to 1 Mbps bitrate
- Error detection/correction
- Message filtering (28 filters)
- 3 TX mailboxes
- 2 RX FIFOs
- Priority-based arbitration
- Automatic retransmission
🚀 Hızlı Başlangıç
içe_aktar hal::can, hal::gpio
// CAN pins: PB8=RX, PB9=TX
gpio.clock_enable(gpio.PORT_B)
gpio.pin_init(gpio.PORT_B, 8, yap mode: gpio.MODE_AF, af: 9 son)
gpio.pin_init(gpio.PORT_B, 9, yap mode: gpio.MODE_AF, af: 9 son)
// Initialize CAN (500 kbps)
değişken can1 = can.init(can.CAN1, yap
bitrate: 500_000,
mode: can.MODE_NORMAL
son)
// Send message
can.send(can1, yap
id: 0x123,
data: [0x01, 0x02, 0x03],
extended_id: yanlış
son)
// Receive message
eğer msg = can.receive(can1, 100) ise yap
io.println("Received ID: 0x{:X}".formatla(msg.id))
son
💡 Örnek: ECU Simulator
içe_aktar hal::can, hal::core
sabit ENGINE_RPM = 0x100
sabit VEHICLE_SPEED = 0x101
sabit COOLANT_TEMP = 0x102
sabit THROTTLE_POS = 0x103
fonksiyon send_rpm(can1: can.Handle, rpm: sayı) yap
değişken data = [
(rpm >> 8) & 0xFF,
rpm & 0xFF
]
can.send(can1, yap
id: ENGINE_RPM,
data: data,
extended_id: yanlış
son)
son
fonksiyon send_speed(can1: can.Handle, speed: sayı) yap
can.send(can1, yap
id: VEHICLE_SPEED,
data: [speed & 0xFF],
extended_id: yanlış
son)
son
fonksiyon send_temp(can1: can.Handle, temp: sayı) yap
// Temperature in Celsius + 40
değişken temp_byte = (temp + 40) & 0xFF
can.send(can1, yap
id: COOLANT_TEMP,
data: [temp_byte],
extended_id: yanlış
son)
son
fonksiyon ana() yap
core.system_init()
// Setup CAN
değişken can1 = can.init(can.CAN1, yap
bitrate: 500_000,
mode: can.MODE_NORMAL
son)
// Configure filter (accept all)
can.filter_config(can1, yap
filter_id: 0,
id: 0x000,
mask: 0x000, // Accept all IDs
fifo: can.FIFO0
son)
// Simulate ECU data
değişken rpm = 800 // Idle RPM
değişken speed = 0
değişken temp = 20
döngü yap
// Send telemetry at 10Hz
send_rpm(can1, rpm)
send_speed(can1, speed)
send_temp(can1, temp)
// Simulate acceleration
eğer rpm < 6000 ise yap
rpm += 100
speed = (rpm / 100) // Simplified
temp += 1 // Engine heats up
değilse yap
rpm = 800 // Back to idle
speed = 0
temp = 20
son
core.delay_ms(100)
son
son
💡 Örnek: CAN Bus Monitor
içe_aktar hal::can
fonksiyon message_name(id: u32) -> yazı yap
dön eşle id yap
0x100 => "Engine RPM",
0x101 => "Vehicle Speed",
0x102 => "Coolant Temp",
0x103 => "Throttle Pos",
0x200 => "Brake Status",
0x300 => "Door Status",
_ => "Unknown"
son
son
fonksiyon parse_data(msg: can.Message) yap
io.print("0x{:03X} [{}] ".formatla(msg.id, msg.dlc))
// Print data bytes
her byte içinde msg.data[0..msg.dlc] için yap
io.print("{:02X} ".formatla(byte))
son
// Interpret known messages
değişken name = message_name(msg.id)
io.print(" // {}", name)
eşle msg.id yap
0x100 => yap // RPM
değişken rpm = (msg.data[0] << 8) | msg.data[1]
io.print(" = {} RPM", rpm)
son,
0x101 => yap // Speed
io.print(" = {} km/h", msg.data[0])
son,
0x102 => yap // Temp
değişken temp = msg.data[0].sayı() - 40
io.print(" = {}°C", temp)
son,
_ => yap son
son
io.println()
son
fonksiyon ana() yap
değişken can1 = can.init(can.CAN1, yap
bitrate: 500_000,
mode: can.MODE_NORMAL
son)
// Accept all messages
can.filter_config(can1, yap
filter_id: 0,
id: 0x000,
mask: 0x000,
fifo: can.FIFO0
son)
io.println("CAN Bus Monitor Started (500 kbps)")
io.println("Press Ctrl+C to exit\n")
döngü yap
// Check for messages (non-blocking)
eğer msg = can.receive(can1, 10) ise yap
parse_data(msg)
son
son
son
💡 Örnek 3: OBD-II Diagnostics
içe_aktar hal::can
sabit OBD_REQUEST = 0x7DF
sabit OBD_RESPONSE = 0x7E8
sabit PID_ENGINE_RPM = 0x0C
sabit PID_VEHICLE_SPEED = 0x0D
fonksiyon obd_request(can1: can.Handle, pid: u8) -> Sonuç[sayı, Hata] yap
can.send(can1, yap
id: OBD_REQUEST,
data: [0x02, 0x01, pid, 0, 0, 0, 0, 0],
dlc: 8
son)?
eğer response = can.receive(can1, 100) ise yap
eğer response.id == OBD_RESPONSE ise yap
dön Tamam(eşle pid yap
PID_ENGINE_RPM => ((response.data[3] << 8) | response.data[4]) / 4,
PID_VEHICLE_SPEED => response.data[3].sayı(),
_ => 0
son)
son
son
dön Hata("Timeout")
son
fonksiyon ana() yap
değişken can1 = can.init(can.CAN1, yap bitrate: 500_000 son)
döngü yap
eğer rpm = obd_request(can1, PID_ENGINE_RPM)? ise yap
io.println("RPM: {}", rpm)
son
core.delay_ms(500)
son
son
📦 Tipler
yapı Message yap
id: u32,
data: [u8; 8],
dlc: u8,
extended_id: mantıksal
son
yapı Config yap
bitrate: sayı,
mode: Mode
son
⚙️ Fonksiyonlar
fonksiyon init(instance: Instance, config: Config) -> Handle
fonksiyon send(handle: Handle, msg: Message) -> Sonuç[Hiçbir, Hata]
fonksiyon receive(handle: Handle, timeout_ms: sayı) -> İsteğe_Bağlı[Message]
fonksiyon filter_config(handle: Handle, config: FilterConfig)
⚠️ Önemli Notlar
- CAN transceiver (TJA1050, MCP2551) gereklidir
- 120Ω termination resistors gerekir (bus'ın her iki ucunda)
- Max bus length: 40m (1 Mbps), 500m (125 kbps)
- Twisted-pair kablo kullanın (CAN_H, CAN_L)
- Filter configuration önemli (yüksek trafikte)
- ISO 11898 standardı kullanılır
🎯 Uygulama Senaryoları
- Otomotiv ECU iletişimi
- OBD-II diagnostics
- Endüstriyel otomasyon (CANopen)
- Denizcilik (NMEA 2000)
📚 Platform Desteği
- STM32 F1/F4: bxCAN (2x CAN)
- STM32 H7: CAN-FD
- ESP32: TWAI
🔗 İlgili Modüller
hal::gpio- CAN TX/RX pinshal::int- CAN interrupts