USART
简要说明
USART(Universal Synchronous Asynchronous Receiver/Transmitter)是一种同步或者异步的串行通信总线接口。当使用同步模式时,需要提供同步时钟,当使用异步模式(UART)的时候,不需要同步时钟,发送和接收方按照严格的格式(波特率和数据帧格式)发送和接收。
USART的特点:
- 空闲时总线保持高电平状态
- 5~9位数据位,低位在前
- 一个起始位
- 可选奇偶检验位
- 可选0.5、1、1.5、2b比特的停止位
USART的传输时序描述如下:
接口描述
csi_usart_initialize
usart_handle_t csi_usart_initialize(int32_t idx, usart_event_cb_t cb_event)
功能描述:
- 通过设备号初始化对应的usart实例,返回usart实例句柄。
参数:
idx
: 设备号cb_event
:- usart实例的事件回调函数(一般在中断上下文执行)。回调函数原型定义见usart_event_cb_t。
返回值:
- NULL: 初始化失败。
- 其它: 初始化成功时的实例句柄。
usart_event_cb_t:
typedef void (*usart_event_cb_t)(int32_t idx, usart_event_e event);
其中idx为设备号,event 为传给回调函数的事件类型。 usart 回调事件枚举类型usart_event_e定义如下:
USART_EVENT_SEND_COMPLETE | 数据发送完成事件 |
---|---|
USART_EVENT_RECEIVE_COMPLETE | 数据接收完成事件 |
USART_EVENT_TRANSFER_COMPLETE | 数据传输完成事件 |
USART_EVENT_TX_COMPLETE | 数据发送完成事件 |
USART_EVENT_TX_UNDERFLOW | 数据发送溢出事件 |
USART_EVENT_RX_OVERFLOW | 数据接收溢出事件 |
USART_EVENT_RX_TIMEOUT | 数据接收超时事件 |
USART_EVENT_RX_BREAK | 数据接收中断事件 |
USART_EVENT_RX_FRAMING_ERROR | 帧数据接收错误事件 |
USART_EVENT_RX_PARITY_ERROR | 数据接收奇偶校验错误事件 |
USART_EVENT_CTS | CTS状态已改变 |
USART_EVENT_DSR | DSR状态已改变 |
USART_EVENT_DCD | DCD状态已改变 |
USART_EVENT_RI | RI状态已改变 |
USART_EVENT_RECEIVED | 数据接收并存在USART FIFO,可调用receive等函数去读取 |
csi_usart_uninitialize
int32_t csi_usart_uninitialize(usart_handle_t handle)
功能描述:
- usart实例反初始化。该接口会停止usart
- 实例正在进行的传输(如果有),并且释放相关的软硬件资源。
参数:
handle
: 实例句柄。
返回值:
- 错误码。
csi_usart_get_capabilities
usart_capabilities_t csi_usart_get_capabilities(int32_t idx)
功能描述:
- 获取usart实例支持的能力。
参数:
idx
: 设备号。
返回值:
- 描述usart能力的结构体。
csi_usart_send
int32_t csi_usart_send(usart_handle_t handle, const void *data, uint32_t num)
功能描述:
- usart启动数据发送。
参数:
handle
: 实例句柄。data
: 待发送数据的缓冲区地址。num
: 待发送数据的长度。
返回值:*
- 错误码。
csi_usart_abort_send
int32_t csi_usart_abort_send(usart_handle_t handle)
功能描述:
- usart数据发送终止。
参数:
handle
: 实例句柄。
返回值:
- 错误码。
csi_usart_receive
int32_t csi_usart_receive(usart_handle_t handle, void *data, uint32_t num)
功能描述:
- usart启动数据接收。
参数:
handle
: 实例句柄。data
: 待接收数据的缓冲区地址。num
: 待接收数据的长度。
返回值:
- 错误码。
csi_usart_receive_query
int32_t csi_usart_receive_query(usart_handle_t handle, void *data, uint32_t num)
功能描述:
- 查询方式从USART读取一定量数据。
参数:
handle
: 实例句柄。data
: 待接收数据的缓冲区地址。num
: 预计接收数据的长度。
返回值:
- 错误码。
csi_usart_abort_receive
int32_t csi_usart_abort_receive(usart_handle_t handle)
功能描述:
- usart数据接收终止。
参数:
handle
: 实例句柄。
返回值:
- 错误码。
csi_usart_transfer
int32_t csi_usart_transfer(usart_handle_t handle, const void *data_out, void *data_in, uint32_t num)
功能描述:
- usart启动数据传输,注意是同步传输。
参数:
handle
: 实例句柄。data_out
: 待发送数据的缓冲区地址。data_in
: 待接收数据的缓冲区地址。num
: 数据的长度。
返回值:
- 错误码。
csi_usart_abort_transfer
int32_t csi_usart_abort_transfer(usart_handle_t handle)
功能描述:
- usart数据传输终止。
参数:
handle
: 实例句柄。
返回值:
- 错误码。
csi_usart_get_status
usart_status_t csi_usart_get_status(usart_handle_t handle)
功能描述:
- 获取当前时刻usart的状态。
参数:
- handle`: 实例句柄。
返回值:
- usart状态的结构体。详见 usart_status_t定义。
usart_status_t:
名字 | 定义 | 备注 |
---|---|---|
tx_busy: 1 | 数据发送忙 | |
rx_busy: 1 | 数据接收忙 | |
tx_underflow: 1 | 数据发送溢出 | |
rx_overflow: 1 | 数据接收溢出 | |
rx_break: 1 | 数据接收中断 | |
rx_framing_error: 1 | 帧数据出错 | |
rx_parity_error: 1 | 数据接收奇偶检验错误 | |
tx_enable: 1 | 发送使能 | |
rx_enable: 1 | 接收使能 |
csi_usart_flush
int32_t csi_usart_flush(usart_handle_t handle, usart_flush_type_e type)
功能描述:
- 清除usart数据缓存。
参数:
handle
: 实例句柄。type
: usart清除数据类型,参看- usart_flush_type_e 定义。
返回值:
- 错误码。
usart_flush_type_e:
名字 | 定义 | 备注 |
---|---|---|
USART_FLUSH_WRITE | 清除写缓存空间 | |
USART_FLUSH_READ | 清除读缓存空间 |
csi_usart_set_interrupt
int32_t csi_usart_set_interrupt(usart_handle_t handle, usart_intr_type_e type, int32_t flag)
功能描述:
- 开关USART的中断。
参数:
handle
: 实例句柄。type
: 中断类型。详见 usart_intr_type_e定义。flag
: 0:关;1:开。
返回值:
- 错误码。
usart_intr_type_e:
名字 | 定义 | 备注 |
---|---|---|
USART_INTR_WRITE | usart写中断 | |
USART_INTR_READ | usart读中断 |
csi_usart_config_baudrate
int32_t csi_usart_config_baudrate(usart_handle_t handle, uint32_t baud)
功能描述:
- 配置usart实例的波特率。
参数:
handle
: 实例句柄。baud
: 波特率。
返回值:
- 错误码。
csi_usart_config_mode
int32_t csi_usart_config_mode(usart_handle_t handle, usart_mode_e mode)
功能描述:
- 配置usart实例的工作模式。
参数:
handle
: 实例句柄。mode
: usart的工作模式。详见 usart_mode_e 定义。
返回值:
- 错误码。
usart_mode_e:
名字 | 定义 | 备注 |
---|---|---|
USART_MODE_ASYNCHRONOUS | usart异步模式 | |
USART_MODE_SYNCHRONOUS_MASTER | usart同步全双工主模式 | |
USART_MODE_SYNCHRONOUS_SLAVE | usart同步全双工从模式 | |
USART_MODE_SLAVE_WIRE | usart半双工单线模式 | |
USART_MODE_SINGLE_IRDA | usart IRDA模式 | |
USART_MODE_SINGLE_SMART_CARD | usart智能卡模式 |
csi_usart_config_parity
int32_t csi_usart_config_parity(usart_handle_t handle, usart_parity_e parity)
功能描述:
- 配置usart实例的奇偶校验模式。
参数:
handle
: 实例句柄。parity
: usart的奇偶校验,参看 usart_parity_e \- 的定义。
返回值:
- 错误码。
usart_parity_e:
名字 | 定义 | 备注 |
---|---|---|
USART_PARITY_NONE | 无奇偶检验 | |
USART_PARITY_EVEN | 偶校验 | |
USART_PARITY_ODD | 奇校验 | |
USART_PARITY_1 | 校验位设置为1 | |
USART_PARITY_0 | 检验位设置为0 |
csi_usart_config_stopbits
int32_t csi_usart_config_stopbits(usart_handle_t handle, usart_stop_bits_e stopbit)
功能描述:
- 配置usart实例的停止位模式。
参数:
handle
: 实例句柄。stopbit
: usart的停止位,参看- usart_stop_bits_e \<usart_stop_bits_e\ * 的定义。
返回值:
- 错误码。
usart_stop_bits_e:
名字 | 定义 | 备注 |
---|---|---|
USART_STOP_BITS_1 | 1停止位 | |
USART_STOP_BITS_2 | 2停止位 | |
USART_STOP_BITS_1_5 | 1.5停止位 | |
USART_STOP_BITS_0_5 | 0.5停止位 |
csi_usart_config_databits
int32_t csi_usart_config_databits(usart_handle_t handle, usart_data_bits_e databits)
功能描述:
参数:
handle
: 实例句柄。databits
: usart的数据位宽,参看- usart_data_bits_e \<usart_data_bits_e\ * 的定义。
返回值:
- 错误码。
usart_data_bits_e:
名字 | 定义 | 备注 |
---|---|---|
USART_DATA_BITS_5 | 5位数据位宽 | |
USART_DATA_BITS_6 | 6位数据位宽 | |
USART_DATA_BITS_7 | 7位数据位宽 | |
USART_DATA_BITS_8 | 8位数据位宽 | |
USART_DATA_BITS_9 | 9位数据位宽 |
csi_usart_getchar
int32_t csi_usart_getchar(usart_handle_t handle, uint8_t *ch)
功能描述:
- 从usart 读取一个字节。
参数:
handle
: 实例句柄。.ch
: 返回读取到的字节。
返回值:
- 错误码。
csi_usart_putchar
int32_t csi_usart_putchar(usart_handle_t handle, uint8_t ch)
功能描述:
- 从usart 发送一个字节。
参数:
handle
: 实例句柄。ch
: 需发送的字节内容。
返回值:
- 错误码。
csi_usart_get_tx_count
uint32_t csi_usart_get_tx_count(usart_handle_t handle)
功能描述:
- 获取设备实例上次已发送的数据个数。
参数:
handle
: 实例句柄。
返回值:
- 已发送的数据个数。
csi_usart_get_rx_count
uint32_t csi_usart_get_rx_count(usart_handle_t handle)
功能描述:
- 获取设备实例上一次已接收的数据个数。
参数:
handle
: 实例句柄。
返回值:
- 已接收的数据个数。
csi_usart_power_control
int32_t csi_usart_power_control(usart_handle_t handle, csi_power_stat_e state)
功能描述:
- 配置设备实例的功耗模式。
参数:
handle
: 实例句柄。state
: 设备实例的功耗模式,参看- csi_power_stat_e \<csi_power_stat_e\ * 的定义。
返回值:
- 错误码。
csi_usart_config_flowctrl
int32_t csi_usart_config_flowctrl(usart_handle_t handle,
usart_flowctrl_type_e flowctrl_type)
功能描述:
- 配置usart实例的流控。
参数:
handle
: 实例句柄。flowctrl_type
: 流控类型,参看- usart_flowctrl_type_e \<usart_flowctrl_type_e\ * 的定义。
返回值:
- 错误码。
usart_flowctrl_type_e:
名字 | 定义 | 备注 |
---|---|---|
USART_FLOWCTRL_NONE | 不带流控 | |
USART_FLOWCTRL_CTS | 支持CTS流控 | |
USART_FLOWCTRL_RTS | 支持RTS流控 | |
USART_FLOWCTRL_CTS_RTS | 同时支持CTS和RTS流控 |
csi_usart_config_clock
int32_t csi_usart_config_clock(usart_handle_t handle, usart_cpol_e cpol, usart_cpha_e cpha)
功能描述:
- 配置usart实例的通信极性与相位。
参数:
handle
: 实例句柄。cpol
: usart的极性,参看 usart_cpol_e 的定义。cpha
: usart的相位,参看 usart_cpha_e 的定义。
返回值:
- 错误码。
usart_cpol_e:
名字 | 定义 | 备注 |
---|---|---|
USART_CPOL0 | 数据在上升沿捕获 | |
USART_CPOL1 | 数据在下降沿捕获 |
usart_cpha_e:
名字 | 定义 | 备注 |
---|---|---|
USART_CPHA0 | 数据在第0个边沿采样 | |
USART_CPHA1 | 数据在第1个边沿采样 |
csi_usart_control_tx
int32_t csi_usart_control_tx(usart_handle_t handle, uint32_t enable)
功能描述:
- 控制usart实例的发送使能。
参数:
handle
: 实例句柄。enable
: 1 - 允许发送数据,0 - 不允许发送数据。
返回值:
- 错误码。
csi_usart_control_rx
int32_t csi_usart_control_rx(usart_handle_t handle, uint32_t enable)
功能描述:
- 控制usart实例的接收使能。
参数:
handle
: 实例句柄。enable
: 1 - 允许接收数据,0 - 不允许接收数据。
返回值:
- 错误码。
csi_usart_control_break
int32_t csi_usart_control_break(usart_handle_t handle, uint32_t enable)
功能描述:
- 控制usart实例的break 帧发送。
参数:
handle
: 实例句柄。enable
: 1 - 开始发送break 帧, 0 - 停止发送break 帧。
返回值:
- 错误码。
使用例程
UART 可使用异步模式或同步模式进行收发数据
本示例,分别使用了异步模式和同步模式,具体如下:
#include "drv_usart.h"
#include "stdio.h"
#include "soc.h"
#include "pin.h"
#define CONFIG_TERMINAL_USART 1
static usart_handle_t g_usart_handle;
static volatile uint8_t rx_async_flag = 0;
static volatile uint8_t tx_async_flag = 0;
static volatile uint8_t rx_trigger_flag = 0;
uint8_t data[18] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R'
};
static int32_t usart_receive_sync(usart_handle_t usart, void *data, uint32_t num)
{
int time_out = 0x7ffff;
usart_status_t status;
csi_usart_receive(usart, data, num);
while (time_out) {
time_out--;
status = csi_usart_get_status(usart);
if (!status.rx_busy) {
break;
}
}
if (0 == time_out) {
return -1;
}
return 0;
}
static int32_t usart_send_sync(usart_handle_t usart, const void *data, uint32_t num)
{
int time_out = 0x7ffff;
usart_status_t status;
csi_usart_send(usart, data, num);
while (time_out) {
time_out--;
status = csi_usart_get_status(usart);
if (!status.tx_busy) {
break;
}
}
if (0 == time_out) {
return -1;
}
return 0;
}
static int32_t usart_receive_async(usart_handle_t usart, void *data, uint32_t num)
{
int time_out = 0x7fffff;
rx_async_flag = 0;
csi_usart_receive(usart, data, num);
while (time_out) {
time_out--;
if (rx_async_flag == 1) {
break;
}
}
if (0 == time_out) {
return -1;
}
rx_async_flag = 0;
return 0;
}
static int32_t usart_send_async(usart_handle_t usart, const void *data, uint32_t num)
{
int time_out = 0x7ffff;
tx_async_flag = 0;
csi_usart_send(usart, data, num);
while (time_out) {
time_out--;
if (tx_async_flag == 1) {
break;
}
}
if (0 == time_out) {
return -1;
}
tx_async_flag = 0;
return 0;
}
static void usart_event_cb(int32_t idx, uint32_t event)
{
uint8_t g_data[15];
switch (event) {
case USART_EVENT_SEND_COMPLETE:
tx_async_flag = 1;
break;
case USART_EVENT_RECEIVE_COMPLETE:
rx_async_flag = 1;
break;
case USART_EVENT_RECEIVED:
csi_usart_receive_query(g_usart_handle, g_data, 15);
default:
break;
}
}
static void usart_event_cb_query(int32_t idx, uint32_t event)
{
uint8_t g_data[15];
uint8_t ret;
switch (event) {
case USART_EVENT_SEND_COMPLETE:
tx_async_flag = 1;
break;
case USART_EVENT_RECEIVE_COMPLETE:
rx_async_flag = 1;
break;
case USART_EVENT_RECEIVED:
ret = csi_usart_receive_query(g_usart_handle, g_data, 15);
csi_usart_send(g_usart_handle, g_data, ret);
rx_trigger_flag = 1;
break;
default:
break;
}
}
static int32_t usart_wait_reply_async(usart_handle_t usart)
{
volatile uint32_t i;
uint8_t ch;
char answer[20];
for (i = 0; i < 20; i++) {
answer[i] = '\0';
}
i = 0;
while (i < 20) {
if (0 == usart_receive_async(usart, &ch, 1)) {
if (ch == '\n' || ch == '\r') {
answer[i] = '\0';
break;
}
if (ch == 127 || ch == '\b') {
if (i > 0) {
i--;
usart_send_async(usart, &ch, 1);
}
} else {
answer[i++] = ch;
usart_send_async(usart, &ch, 1);
}
}
}
if ((i == 1) && (answer[0] == 'y')) {
return 1;
} else if ((i == 1) && (answer[0] == 'n')) {
return 0;
}
return 2;
}
static int32_t usart_wait_reply(usart_handle_t usart)
{
volatile uint32_t i;
uint8_t ch;
char answer[20];
for (i = 0; i < 20; i++) {
answer[i] = '\0';
}
i = 0;
while (i < 20) {
if (0 == usart_receive_sync(usart, &ch, 1)) {
if (ch == '\n' || ch == '\r') {
answer[i] = '\0';
break;
}
if (ch == 127 || ch == '\b') {
if (i > 0) {
i--;
usart_send_sync(usart, &ch, 1);
}
} else {
answer[i++] = ch;
usart_send_sync(usart, &ch, 1);
}
}
}
if ((i == 1) && (answer[0] == 'y')) {
return 1;
} else if ((i == 1) && (answer[0] == 'n')) {
return 0;
}
return 2;
}
static int32_t usart_test_async_mode(usart_handle_t usart, int32_t uart_idx)
{
uint32_t get;
int32_t ret;
///////////////////* async mode ///////////////////////
/* Insure prompt information is displayed */
/* Changes usart mode to interrupt mode */
csi_usart_uninitialize(usart);
usart = csi_usart_initialize(uart_idx, (usart_event_cb_t)usart_event_cb);
if (usart == NULL) {
return -1;
}
g_usart_handle = usart;
ret = csi_usart_config(usart, 115200, USART_MODE_ASYNCHRONOUS, USART_PARITY_NONE, USART_STOP_BITS_1, USART_DATA_BITS_8);
if (ret < 0) {
printf("csi_usart_config error %x\n", ret);
return -1;
}
printf("\r\t(async mode ): Output is---\n\t\t");
usart_send_async(usart, data, sizeof(data));
printf("- - - [y/n] ");
while (1) {
/* wait for the input*/
get = usart_wait_reply_async(usart);
if ((get == 1) || (get == 0)) {
break;
} else {
printf("\n\tPlease enter 'y' or 'n' ");
}
}
if (get == 1) {
printf("\t- - -PASS\n");
} else {
printf("\t- - -FAILURE\n");
return -1;
}
return 0;
}
static int32_t usart_test_sync_mode(usart_handle_t usart)
{
uint32_t get;
///////////////////* sync mode *//////////////////////////
printf("\n\n\t- - - Testing usart mode...\n");
printf("\r\t(sync mode ): Output is---\n\t\t");
usart_send_sync(usart, data, sizeof(data));
printf("- - - [y/n] ");
/* wait for the input*/
while (1) {
get = usart_wait_reply(usart);
if ((get == 1) || (get == 0)) {
break;
} else {
printf("\n\tPlease enter 'y' or 'n' ");
}
}
if (get == 1) {
printf("\t- - -PASS\n");
} else {
printf("\t- - -FAILURE\n");
return -1;
}
return 0;
}
int _usart_test(usart_handle_t usart, int32_t uart_idx)
{
uint32_t get;
//char input_char1,input_char2;
int32_t ret;
ret = usart_test_sync_mode(usart);
if (ret < 0) {
printf("usart_test_sync_mode error %x\n", ret);
return -1;
}
/* test async mode */
ret = usart_test_async_mode(usart, uart_idx);
if (ret < 0) {
printf("usart_test_async_mode error %x\n", ret);
return -1;
}
return 0;
}
void example_pin_usart_init(void)
{
drv_pinmux_config(EXAMPLE_PIN_USART_TX, EXAMPLE_PIN_USART_TX_FUNC);
drv_pinmux_config(EXAMPLE_PIN_USART_RX, EXAMPLE_PIN_USART_RX_FUNC);
}
int test_usart(int32_t uart_idx)
{
usart_handle_t p_csi_usart;
int32_t ret;
/* init the USART*/
p_csi_usart = csi_usart_initialize(uart_idx, NULL);
if (p_csi_usart == NULL) {
printf("csi_usart_initialize error\n");
return -1;
}
example_pin_usart_init();
/* config the USART */
ret = csi_usart_config(p_csi_usart, 115200, USART_MODE_ASYNCHRONOUS, USART_PARITY_NONE, USART_STOP_BITS_1, USART_DATA_BITS_8);
if (ret < 0) {
printf("csi_usart_config error %x\n", ret);
return -1;
}
ret = _usart_test(p_csi_usart, uart_idx);
if (ret < 0) {
printf("_usart_test error %x\n", ret);
return -1;
}
printf("test_usart OK\n");
return 0;
}
int example_usart(void)
{
int ret;
ret = test_usart(EXAMPLE_USART_IDX);
if (ret < 0) {
printf("test_usart failed\n");
return -1;
}
return 0;
}
int main(void)
{
return example_usart();
}