kopia lustrzana https://github.com/micropython/micropython
stmhal: Fix UART so bits counts number of data bits, not incl parity.
Addresses issue #950.pull/954/head
rodzic
1559a97810
commit
4029f51842
|
@ -13,7 +13,10 @@ UART objects can be created and initialised using::
|
||||||
uart = UART(1, 9600) # init with given baudrate
|
uart = UART(1, 9600) # init with given baudrate
|
||||||
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
|
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
|
||||||
|
|
||||||
Bits can be 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2.
|
Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2.
|
||||||
|
|
||||||
|
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
|
||||||
|
only 7 and 8 bits are supported.
|
||||||
|
|
||||||
A UART object acts like a stream object and reading and writing is done
|
A UART object acts like a stream object and reading and writing is done
|
||||||
using the standard stream methods::
|
using the standard stream methods::
|
||||||
|
@ -57,35 +60,44 @@ Constructors
|
||||||
Methods
|
Methods
|
||||||
-------
|
-------
|
||||||
|
|
||||||
.. method:: uart.any()
|
|
||||||
|
|
||||||
Return ``True`` if any characters waiting, else ``False``.
|
|
||||||
|
|
||||||
.. method:: uart.deinit()
|
|
||||||
|
|
||||||
Turn off the UART bus.
|
|
||||||
|
|
||||||
.. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, timeout_char=0, read_buf_len=64)
|
.. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, timeout_char=0, read_buf_len=64)
|
||||||
|
|
||||||
Initialise the UART bus with the given parameters:
|
Initialise the UART bus with the given parameters:
|
||||||
|
|
||||||
- ``baudrate`` is the clock rate.
|
- ``baudrate`` is the clock rate.
|
||||||
- ``bits`` is the number of bits per byte, 8 or 9.
|
- ``bits`` is the number of bits per character, 7, 8 or 9.
|
||||||
- ``parity`` is the parity, ``None``, 0 (even) or 1 (odd).
|
- ``parity`` is the parity, ``None``, 0 (even) or 1 (odd).
|
||||||
- ``stop`` is the number of stop bits, 1 or 2.
|
- ``stop`` is the number of stop bits, 1 or 2.
|
||||||
- ``timeout`` is the timeout in milliseconds to wait for the first character.
|
- ``timeout`` is the timeout in milliseconds to wait for the first character.
|
||||||
- ``timeout_char`` is the timeout in milliseconds to wait between characters.
|
- ``timeout_char`` is the timeout in milliseconds to wait between characters.
|
||||||
- ``read_buf_len`` is the character length of the read buffer (0 to disable).
|
- ``read_buf_len`` is the character length of the read buffer (0 to disable).
|
||||||
|
|
||||||
|
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
|
||||||
|
only 7 and 8 bits are supported.
|
||||||
|
|
||||||
|
.. method:: uart.deinit()
|
||||||
|
|
||||||
|
Turn off the UART bus.
|
||||||
|
|
||||||
|
.. method:: uart.any()
|
||||||
|
|
||||||
|
Return ``True`` if any characters waiting, else ``False``.
|
||||||
|
|
||||||
.. method:: uart.read([nbytes])
|
.. method:: uart.read([nbytes])
|
||||||
|
|
||||||
|
Read characters. If ``nbytes`` is specified then read at most that many bytes.
|
||||||
|
|
||||||
|
*Note:* for 9 bit characters each character takes 2 bytes, ``nbytes`` must be even,
|
||||||
|
and the number of characters is ``nbytes/2``.
|
||||||
|
|
||||||
.. method:: uart.readall()
|
.. method:: uart.readall()
|
||||||
|
|
||||||
|
Read as much data as possible.
|
||||||
|
|
||||||
.. method:: uart.readchar()
|
.. method:: uart.readchar()
|
||||||
|
|
||||||
Receive a single character on the bus.
|
Receive a single character on the bus.
|
||||||
|
|
||||||
Return value: The character read, as an integer. Returns -1 on timeout.
|
Return value: The character read, as an integer. Returns -1 on timeout.
|
||||||
|
|
||||||
.. method:: uart.readinto(buf[, nbytes])
|
.. method:: uart.readinto(buf[, nbytes])
|
||||||
|
|
|
@ -80,13 +80,14 @@
|
||||||
|
|
||||||
struct _pyb_uart_obj_t {
|
struct _pyb_uart_obj_t {
|
||||||
mp_obj_base_t base;
|
mp_obj_base_t base;
|
||||||
pyb_uart_t uart_id;
|
UART_HandleTypeDef uart; // this is 17 words big
|
||||||
bool is_enabled;
|
|
||||||
UART_HandleTypeDef uart;
|
|
||||||
IRQn_Type irqn;
|
IRQn_Type irqn;
|
||||||
|
pyb_uart_t uart_id : 8;
|
||||||
|
bool is_enabled : 1;
|
||||||
|
byte char_width; // 0 for 7,8 bit chars, 1 for 9 bit chars
|
||||||
|
uint16_t char_mask; // 0x7f for 7 bit, 0xff for 8 bit, 0x1ff for 9 bit
|
||||||
uint16_t timeout; // timeout waiting for first char
|
uint16_t timeout; // timeout waiting for first char
|
||||||
uint16_t timeout_char; // timeout waiting between chars
|
uint16_t timeout_char; // timeout waiting between chars
|
||||||
uint16_t char_width; // 0 for 7,8 bit chars, 1 for 9 bit chars
|
|
||||||
uint16_t read_buf_len; // len in chars; buf can hold len-1 chars
|
uint16_t read_buf_len; // len in chars; buf can hold len-1 chars
|
||||||
volatile uint16_t read_buf_head; // indexes first empty slot
|
volatile uint16_t read_buf_head; // indexes first empty slot
|
||||||
uint16_t read_buf_tail; // indexes first full slot (not full if equals head)
|
uint16_t read_buf_tail; // indexes first full slot (not full if equals head)
|
||||||
|
@ -280,7 +281,7 @@ int uart_rx_char(pyb_uart_obj_t *self) {
|
||||||
return data;
|
return data;
|
||||||
} else {
|
} else {
|
||||||
// no buffering
|
// no buffering
|
||||||
return self->uart.Instance->DR;
|
return self->uart.Instance->DR & self->char_mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,6 +316,7 @@ void uart_irq_handler(mp_uint_t uart_id) {
|
||||||
|
|
||||||
if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET) {
|
if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET) {
|
||||||
int data = self->uart.Instance->DR; // clears UART_FLAG_RXNE
|
int data = self->uart.Instance->DR; // clears UART_FLAG_RXNE
|
||||||
|
data &= self->char_mask;
|
||||||
if (self->read_buf_len != 0) {
|
if (self->read_buf_len != 0) {
|
||||||
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
|
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
|
||||||
if (next_head != self->read_buf_tail) {
|
if (next_head != self->read_buf_tail) {
|
||||||
|
@ -340,9 +342,12 @@ STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void
|
||||||
if (!self->is_enabled) {
|
if (!self->is_enabled) {
|
||||||
print(env, "UART(%u)", self->uart_id);
|
print(env, "UART(%u)", self->uart_id);
|
||||||
} else {
|
} else {
|
||||||
|
mp_int_t bits = (self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9);
|
||||||
|
if (self->uart.Init.Parity != UART_PARITY_NONE) {
|
||||||
|
bits -= 1;
|
||||||
|
}
|
||||||
print(env, "UART(%u, baudrate=%u, bits=%u, parity=",
|
print(env, "UART(%u, baudrate=%u, bits=%u, parity=",
|
||||||
self->uart_id, self->uart.Init.BaudRate,
|
self->uart_id, self->uart.Init.BaudRate, bits);
|
||||||
self->uart.Init.WordLength == UART_WORDLENGTH_8B ? 8 : 9);
|
|
||||||
if (self->uart.Init.Parity == UART_PARITY_NONE) {
|
if (self->uart.Init.Parity == UART_PARITY_NONE) {
|
||||||
print(env, "None");
|
print(env, "None");
|
||||||
} else {
|
} else {
|
||||||
|
@ -359,7 +364,7 @@ STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void
|
||||||
/// Initialise the UART bus with the given parameters:
|
/// Initialise the UART bus with the given parameters:
|
||||||
///
|
///
|
||||||
/// - `baudrate` is the clock rate.
|
/// - `baudrate` is the clock rate.
|
||||||
/// - `bits` is the number of bits per byte, 8 or 9.
|
/// - `bits` is the number of bits per byte, 7, 8 or 9.
|
||||||
/// - `parity` is the parity, `None`, 0 (even) or 1 (odd).
|
/// - `parity` is the parity, `None`, 0 (even) or 1 (odd).
|
||||||
/// - `stop` is the number of stop bits, 1 or 2.
|
/// - `stop` is the number of stop bits, 1 or 2.
|
||||||
/// - `timeout` is the timeout in milliseconds to wait for the first character.
|
/// - `timeout` is the timeout in milliseconds to wait for the first character.
|
||||||
|
@ -384,20 +389,40 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
|
||||||
// set the UART configuration values
|
// set the UART configuration values
|
||||||
memset(&self->uart, 0, sizeof(self->uart));
|
memset(&self->uart, 0, sizeof(self->uart));
|
||||||
UART_InitTypeDef *init = &self->uart.Init;
|
UART_InitTypeDef *init = &self->uart.Init;
|
||||||
|
|
||||||
|
// baudrate
|
||||||
init->BaudRate = args[0].u_int;
|
init->BaudRate = args[0].u_int;
|
||||||
init->WordLength = args[1].u_int == 8 ? UART_WORDLENGTH_8B : UART_WORDLENGTH_9B;
|
|
||||||
|
// parity
|
||||||
|
mp_int_t bits = args[1].u_int;
|
||||||
if (args[2].u_obj == mp_const_none) {
|
if (args[2].u_obj == mp_const_none) {
|
||||||
init->Parity = UART_PARITY_NONE;
|
init->Parity = UART_PARITY_NONE;
|
||||||
} else {
|
} else {
|
||||||
mp_int_t parity = mp_obj_get_int(args[2].u_obj);
|
mp_int_t parity = mp_obj_get_int(args[2].u_obj);
|
||||||
init->Parity = (parity & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN;
|
init->Parity = (parity & 1) ? UART_PARITY_ODD : UART_PARITY_EVEN;
|
||||||
|
bits += 1; // STs convention has bits including parity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// number of bits
|
||||||
|
if (bits == 8) {
|
||||||
|
init->WordLength = UART_WORDLENGTH_8B;
|
||||||
|
} else if (bits == 9) {
|
||||||
|
init->WordLength = UART_WORDLENGTH_9B;
|
||||||
|
} else {
|
||||||
|
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unsupported combination of bits and parity"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop bits
|
||||||
switch (args[3].u_int) {
|
switch (args[3].u_int) {
|
||||||
case 1: init->StopBits = UART_STOPBITS_1; break;
|
case 1: init->StopBits = UART_STOPBITS_1; break;
|
||||||
default: init->StopBits = UART_STOPBITS_2; break;
|
default: init->StopBits = UART_STOPBITS_2; break;
|
||||||
}
|
}
|
||||||
init->Mode = UART_MODE_TX_RX;
|
|
||||||
|
// flow control
|
||||||
init->HwFlowCtl = args[4].u_int;
|
init->HwFlowCtl = args[4].u_int;
|
||||||
|
|
||||||
|
// extra config (not yet configurable)
|
||||||
|
init->Mode = UART_MODE_TX_RX;
|
||||||
init->OverSampling = UART_OVERSAMPLING_16;
|
init->OverSampling = UART_OVERSAMPLING_16;
|
||||||
|
|
||||||
// init UART (if it fails, it's because the port doesn't exist)
|
// init UART (if it fails, it's because the port doesn't exist)
|
||||||
|
@ -412,8 +437,14 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
|
||||||
// setup the read buffer
|
// setup the read buffer
|
||||||
m_del(byte, self->read_buf, self->read_buf_len << self->char_width);
|
m_del(byte, self->read_buf, self->read_buf_len << self->char_width);
|
||||||
if (init->WordLength == UART_WORDLENGTH_9B && init->Parity == UART_PARITY_NONE) {
|
if (init->WordLength == UART_WORDLENGTH_9B && init->Parity == UART_PARITY_NONE) {
|
||||||
|
self->char_mask = 0x1ff;
|
||||||
self->char_width = CHAR_WIDTH_9BIT;
|
self->char_width = CHAR_WIDTH_9BIT;
|
||||||
} else {
|
} else {
|
||||||
|
if (init->WordLength == UART_WORDLENGTH_9B || init->Parity == UART_PARITY_NONE) {
|
||||||
|
self->char_mask = 0xff;
|
||||||
|
} else {
|
||||||
|
self->char_mask = 0x7f;
|
||||||
|
}
|
||||||
self->char_width = CHAR_WIDTH_8BIT;
|
self->char_width = CHAR_WIDTH_8BIT;
|
||||||
}
|
}
|
||||||
self->read_buf_head = 0;
|
self->read_buf_head = 0;
|
||||||
|
|
Ładowanie…
Reference in New Issue