📡 hal::usart
Universal Synchronous/Asynchronous Receiver/Transmitter
407 lines
~20 function
UART/USART
📖 Overview
USART/UART modülü, seri haberleşme protokolüdür. GPS, GSM modüller, sensörler ve PC ile haberleşme for kullanılır.
🔑 Key Features
- Asynchronous (UART) mode
- Synchronous (USART) mode
- Configurable baud rates (1200-12Mbps)
- 7/8/9 bit data
- Parity: None/Even/Odd
- 1/2 stop bits
- Hardware flow control (RTS/CTS)
- DMA support
- Interrupt-driven TX/RX
🚀 Quick Start
import hal::usart, hal::gpio
// GPIO setup for USART1
gpio.clock_enable(gpio.PORT_A)
gpio.pin_init(gpio.PORT_A, 9, do // TX
mode: gpio.MODE_AF,
af: 7 // AF7 = USART1
end)
gpio.pin_init(gpio.PORT_A, 10, do // RX
mode: gpio.MODE_AF,
pull: gpio.PULL_UP,
af: 7
end)
// USART init
let uart = usart.init(usart.USART1, do
baud_rate: 115200,
data_bits: usart.DATA_8BIT,
parity: usart.PARITY_NONE,
stop_bits: usart.STOP_1BIT
end)
// Send data
usart.write(uart, "Hello World!\n")
// Receive data
let data = usart.read(uart, 100) // Read up to 100 bytes
💡 Example 1: Serial Console
import hal::usart, hal::gpio, hal::core
function uart_print(uart: usart.Handle, msg: str) do
usart.write(uart, msg)
end
function uart_println(uart: usart.Handle, msg: str) do
usart.write(uart, msg + "\r\n")
end
function ana() do
core.system_init()
core.clock_config(72_000_000)
// Setup USART1 GPIO (PA9=TX, PA10=RX)
gpio.clock_enable(gpio.PORT_A)
gpio.pin_init(gpio.PORT_A, 9, do
mode: gpio.MODE_AF,
speed: gpio.SPEED_HIGH,
af: 7
end)
gpio.pin_init(gpio.PORT_A, 10, do
mode: gpio.MODE_AF,
pull: gpio.PULL_UP,
af: 7
end)
// Initialize USART
usart.clock_enable(usart.USART1)
let uart = usart.init(usart.USART1, do
baud_rate: 115200,
data_bits: usart.DATA_8BIT,
parity: usart.PARITY_NONE,
stop_bits: usart.STOP_1BIT,
flow_control: usart.FLOW_NONE
end)
uart_println(uart, "BERK v1.0.0 Console")
uart_println(uart, "Type 'help' for commands")
let buffer = ""
loop do
// Check if data available
if usart.available(uart) > 0 ise do
let ch = usart.read_byte(uart)
if ch == '\r' veya ch == '\n' ise do
if buffer.uzunluk() > 0 ise do
uart_println(uart, "")
process_command(uart, buffer)
buffer = ""
uart_print(uart, "> ")
end
değilse if ch == '\b' ise do // Backspace
if buffer.uzunluk() > 0 ise do
buffer = buffer[0..buffer.uzunluk()-1]
uart_print(uart, "\b \b") // Erase character
end
değilse do
buffer += ch
usart.write_byte(uart, ch) // Echo
end
end
end
end
function process_command(uart: usart.Handle, cmd: str) do
if cmd == "help" ise do
uart_println(uart, "Available commands:")
uart_println(uart, " help - Show this message")
uart_println(uart, " status - System status")
uart_println(uart, " reset - Reset system")
uart_println(uart, " info - System info")
değilse if cmd == "status" ise do
let uptime = core.uptime_ms() / 1000
uart_println(uart, "System Status:")
uart_println(uart, " Uptime: " + uptime.yazıya() + "s")
uart_println(uart, " Clock: 72 MHz")
uart_println(uart, " Free RAM: 64 KB")
değilse if cmd == "reset" ise do
uart_println(uart, "Resetting...")
core.delay_ms(100)
core.system_reset()
değilse if cmd == "info" ise do
uart_println(uart, "BERK Embedded System")
uart_println(uart, "Version: 1.0.0")
uart_println(uart, "Platform: STM32F103")
değilse do
uart_println(uart, "Unknown command: " + cmd)
end
end
💡 Example 2: GPS Parser (NMEA)
import hal::usart, string
struct GPSData do
latitude: float,
longitude: float,
altitude: float,
speed: float,
satellites: int,
valid: bool
end
function parse_nmea(sentence: str) -> Optional[GPSData] do
// Parse GPGGA sentence: $GPGGA,time,lat,N,lon,E,quality,sats,hdop,alt,M,...
if sentence.starts_with("$GPGGA") değilse do
return None
end
let parts = sentence.split(",")
if parts.uzunluk() < 15 ise do
return None
end
let quality = parts[6].parse_int()?
if quality == 0 ise do // Invalid fix
return None
end
// Parse latitude (DDMM.MMMM format)
let lat_str = parts[2]
let lat_deg = lat_str[0..2].parse_int()?
let lat_min = lat_str[2..].parse_float()?
let latitude = lat_deg.float() + lat_min / 60.0
if parts[3] == "S" ise do
latitude = -latitude
end
// Parse longitude (DDDMM.MMMM format)
let lon_str = parts[4]
let lon_deg = lon_str[0..3].parse_int()?
let lon_min = lon_str[3..].parse_float()?
let longitude = lon_deg.float() + lon_min / 60.0
if parts[5] == "W" ise do
longitude = -longitude
end
return Some(GPSData do
latitude: latitude,
longitude: longitude,
altitude: parts[9].parse_float()?,
speed: 0.0,
satellites: parts[7].parse_int()?,
valid: true
end)
end
function ana() do
// Setup USART for GPS (9600 baud, typical for GPS)
let gps_uart = usart.init(usart.USART2, do
baud_rate: 9600,
data_bits: usart.DATA_8BIT,
parity: usart.PARITY_NONE,
stop_bits: usart.STOP_1BIT
end)
let buffer = ""
loop do
if usart.available(gps_uart) > 0 ise do
let ch = usart.read_byte(gps_uart)
if ch == '\n' ise do
// Process complete sentence
if gps_data = parse_nmea(buffer) ise do
io.println("GPS Fix:")
io.println(" Lat: {:.6f}".formatla(gps_data.latitude))
io.println(" Lon: {:.6f}".formatla(gps_data.longitude))
io.println(" Alt: {:.1f}m".formatla(gps_data.altitude))
io.println(" Sats: {}".formatla(gps_data.satellites))
end
buffer = ""
değilse if ch != '\r' ise do
buffer += ch
end
end
core.delay_ms(10)
end
end
💡 Example 3: AT Command Interface (GSM)
import hal::usart, hal::core
struct GSMModem do
uart: usart.Handle
end
function send_at_command(modem: GSMModem, cmd: str, timeout_ms: int) -> Result[str, Error] do
// Send command
usart.write(modem.uart, cmd + "\r\n")
// Wait for response
let response = ""
let start_time = core.millis()
loop do
if usart.available(modem.uart) > 0 ise do
let ch = usart.read_byte(modem.uart)
response += ch
// Check for termination
if response.ends_with("OK\r\n") veya response.ends_with("ERROR\r\n") ise do
return Ok(response)
end
end
// Timeout check
if core.millis() - start_time > timeout_ms ise do
return Error("AT command timeout")
end
core.delay_ms(10)
end
end
function gsm_init() -> Result[GSMModem, Error] do
let uart = usart.init(usart.USART3, do
baud_rate: 115200,
data_bits: usart.DATA_8BIT,
parity: usart.PARITY_NONE,
stop_bits: usart.STOP_1BIT
end)
let modem = GSMModem do uart: uart end
// Test communication
send_at_command(modem, "AT", 1000)?
// Disable echo
send_at_command(modem, "ATE0", 1000)?
// Check SIM card
let sim_status = send_at_command(modem, "AT+CPIN?", 1000)?
if sim_status.contains("READY") değilse do
return Error("SIM card not ready")
end
return Ok(modem)
end
function send_sms(modem: GSMModem, phone: str, message: str) -> Result[None, Error] do
// Set text mode
send_at_command(modem, "AT+CMGF=1", 1000)?
// Set phone number
send_at_command(modem, "AT+CMGS=\"" + phone + "\"", 1000)?
// Send message
usart.write(modem.uart, message)
usart.write_byte(modem.uart, 0x1A) // Ctrl+Z
let response = send_at_command(modem, "", 10000)?
if response.contains("OK") değilse do
return Error("Failed to send SMS")
end
return Ok(None)
end
function ana() do
let modem = gsm_init()?
io.println("GSM Modem ready!")
// Send alert SMS
send_sms(modem, "+905551234567", "BERK System Alert: Temperature exceeded 50°C")?
io.println("SMS sent successfully!")
end
⚙️ Baud Rates
const BAUD_1200 = 1200
const BAUD_2400 = 2400
const BAUD_4800 = 4800
const BAUD_9600 = 9600 // GPS, simple devices
const BAUD_19200 = 19200
const BAUD_38400 = 38400
const BAUD_57600 = 57600
const BAUD_115200 = 115200 // PC communication, GSM
const BAUD_230400 = 230400
const BAUD_460800 = 460800
const BAUD_921600 = 921600
⚠️ Important Notes
- TX/RX pinlerini true alternatif functiona ayarlayın
- Baud rate hesabı clock frequency'ye bağlıdır
- Uzun kablolarda düşük baud rate kullanın
- RX buffer overflow'dan kaçının (interrupt/DMA kullanın)
- 3.3V-5V level shifting gerekebilir
🔗 Related Modules
hal::gpio- TX/RX pin configurationhal::dma- DMA transfershal::int- USART interrupts