UART 使用教程
"# JL701n UART 使用教程
概述
本教程详细介绍如何在 JL701n 芯片上使用 UART 进行串口通信。该示例展示了 UART2 的初始化、数据收发、中断处理等核心功能。
目录
- 代码结构分析
- 核心功能说明
- 配置参数详解
- 使用步骤
- API 接口说明
- 注意事项
- 完整使用示例
代码结构分析
头文件包含
```c
#include “app_config.h” // 应用配置头文件
#include “system/includes.h” // 系统通用头文件
#include “asm/uart_dev.h” // UART设备驱动头文件
```
全局变量
```c
static u8 uart_cbuf[32] attribute((aligned(4))); // UART接收缓冲区,4字节对齐
const uart_bus_t *uart_bus = NULL; // UART总线句柄
static u8 my_test_buf[1024]; // 测试数据缓冲区
```
核心功能说明
1. UART 中断处理函数
```c
static void uart_isr_handle(void *arg, u32 status)
```
功能: 处理 UART 中断事件
参数:
- `arg`: UART 总线指针
- `status`: 中断状态标志
支持的中断类型:
- `UT_RX`: 接收满帧数据中断(达到 frame_length 字节)
- `UT_RX_OT`: 接收超时中断(不满 frame_length 字节)
- `UT_TX`: 发送完成中断
2. UART 初始化函数
```c
void user_uart_open(void)
```
功能: 初始化并打开 UART2 设备
配置参数:
- 发送引脚: `TCFG_UART2_TX_PORT`
- 接收引脚: `TCFG_UART2_RX_PORT`
- 波特率: `TCFG_UART2_BAUDRATE`
- 帧长度: 16 字节
- 接收超时: 100ms
3. 数据发送函数
```c
void user_uart2_send(void *buf, u32 len)
```
功能: 通过 UART2 发送数据
参数:
- `buf`: 发送数据缓冲区
- `len`: 数据长度
4. UART 关闭函数
```c
void user_uart_close(void)
```
功能: 关闭 UART2 设备并释放资源
配置参数详解
UART 平台数据结构
```c
struct uart_platform_data_t {
u32 tx_pin; // 发送引脚
u32 rx_pin; // 接收引脚
u8 *rx_cbuf; // 接收缓冲区
u32 rx_cbuf_size; // 缓冲区大小
u32 frame_length; // 帧长度(触发中断的字节数)
u32 rx_timeout; // 接收超时时间(ms)
void (*isr_cbfun)(void *arg, u32 status); // 中断回调函数
u32 baud; // 波特率
u8 is_9bit; // 是否9位数据位
};
```
关键配置说明
参数 | 说明 | 示例值 |
---|---|---|
`tx_pin` | 发送引脚 | `TCFG_UART2_TX_PORT` |
`rx_pin` | 接收引脚 | `TCFG_UART2_RX_PORT` |
`rx_cbuf` | 接收缓冲区 | `uart_cbuf` |
`rx_cbuf_size` | 缓冲区大小 | `32` |
`frame_length` | 帧长度 | `16` |
`rx_timeout` | 接收超时 | `100` |
`baud` | 波特率 | `TCFG_UART2_BAUDRATE` |
`is_9bit` | 数据位 | `0` (8位) |
使用步骤
1. 初始化 UART
```c
// 在应用初始化阶段调用
user_uart_open();
```
2. 发送数据
```c
u8 send_data[] = “Hello UART!”;
user_uart2_send(send_data, sizeof(send_data) - 1);
```
3. 接收数据
数据接收通过中断自动处理,在 `uart_isr_handle` 函数中处理接收到的数据。
4. 关闭 UART
```c
// 在应用结束时调用
user_uart_close();
```
API 接口说明
主要函数接口
函数名 | 功能 | 参数 | 返回值 |
---|---|---|---|
`user_uart_open()` | 打开UART设备 | 无 | 无 |
`user_uart_close()` | 关闭UART设备 | 无 | 无 |
`user_uart2_send()` | 发送数据 | `buf`: 数据缓冲区 `len`: 数据长度 | 无 |
`uart_isr_handle()` | 中断处理函数 | `arg`: UART句柄 `status`: 中断状态 | 无 |
中断状态标志
标志 | 含义 | 触发条件 |
---|---|---|
`UT_RX` | 接收满帧 | 接收到 frame_length 字节数据 |
`UT_RX_OT` | 接收超时 | 接收不满 frame_length 字节但超时 |
`UT_TX` | 发送完成 | 数据发送完成 |
注意事项
1. 中断处理限制
- 不要在中断中调用 `ubus->write()`,因为中断不能等待信号量
- 建议在中断中只读取数据,通过信号量通知任务处理
2. 缓冲区管理
- 接收缓冲区必须4字节对齐:`attribute((aligned(4)))`
- 缓冲区大小建议为2的幂次,便于管理
3. 引脚配置
- 确保 TX/RX 引脚在配置文件中正确定义
- 发送引脚需要配置为高驱动模式
4. 波特率设置
- 确保波特率与通信设备匹配
- 常用波特率:9600, 19200, 38400, 57600, 115200
完整使用示例
基本使用流程
```c
#include “app_config.h”
#include “system/includes.h”
#include “asm/uart_dev.h”
// 1. 初始化UART
void app_init(void)
{
user_uart_open();
}
// 2. 发送数据示例
void send_test_data(void)
{
u8 test_data[] = “UART Test Message\r\n”;
user_uart2_send(test_data, sizeof(test_data) - 1);
}
// 3. 应用主循环
void app_main_loop(void)
{
while(1) {
// 定期发送数据
send_test_data();
os_time_dly(1000); // 延时1秒
}
}
// 4. 应用退出
void app_exit(void)
{
user_uart_close();
}
```
高级使用示例(带任务处理)
```c
// 定义信号量
static os_sem_t uart_rx_sem;
// 修改中断处理函数
static void uart_isr_handle(void *arg, u32 status)
{
if (status == UT_RX) {
// 在中断中只读取数据,不处理
uart_bus->read(my_test_buf, 16, 100);
// 发送信号量通知任务处理
os_sem_post(&uart_rx_sem);
}
}
// 创建UART处理任务
static void uart_task(void *arg)
{
while(1) {
// 等待接收信号量
os_sem_pend(&uart_rx_sem, 0);
// 处理接收到的数据printf(\"Received: \");put_buf(my_test_buf, 16);// 转发到蓝牙if (bluetooth_spp_user_send_data_check()) {bluetooth_spp_user_send_data(my_test_buf, 16);}
}
}
// 在UART打开时创建任务
void user_uart_open(void)
{
// … 原有初始化代码 …
if (uart_bus != NULL) {// 创建信号量os_sem_create(&uart_rx_sem, 0);// 创建处理任务os_task_create(uart_task, NULL, 31, 512, 0, \"uart_task\");
}
}
```
故障排除
常见问题
-
UART 打开失败
- 检查引脚配置是否正确
- 确认引脚未被其他功能占用
-
数据接收异常
- 检查波特率是否匹配
- 确认帧长度设置是否合适
-
发送数据丢失
- 检查发送缓冲区是否足够
- 确认发送引脚配置正确
-
中断不触发
- 检查中断回调函数是否正确注册
- 确认中断使能状态
调试建议
- 使用 `printf` 输出调试信息
- 检查 `put_buf` 输出确认数据正确性
- 使用示波器检查引脚信号
- 逐步验证配置参数
总结
本教程详细介绍了 JL701n 芯片 UART 的使用方法,包括初始化、数据收发、中断处理等核心功能。通过合理配置参数和正确处理中断,可以实现稳定可靠的串口通信功能。
建议在实际使用中根据具体需求调整配置参数,并注意遵循中断处理的最佳实践。"
#include "app_config.h"
#include "system/includes.h"
#include "asm/uart_dev.h"static u8 uart_cbuf[32] __attribute__((aligned(4)));
const uart_bus_t *uart_bus = NULL;static u8 my_test_buf[1024];
void gpio_change(void *priv);
static void uart_isr_handle(void *arg, u32 status)
{const uart_bus_t *ubus = arg;struct sys_event e;//不要在中断里面调用ubus->write(),因为中断不能pend信号量if (status == UT_RX) { //每满frame_length字节则产生一次中断printf("uart_rx_isr\n");uart_bus->read(my_test_buf, 16, 100);put_buf(my_test_buf, 16);if (bluetooth_spp_user_send_data_check()) {bluetooth_spp_user_send_data(my_test_buf, 16);}//一般这里os_sem_post(&rx_sem); post消息到自己的任务里面把数据读出来使用}if (status == UT_RX_OT) { //outtime : 接收到不满frame_length字节进这里printf("uart_rx_ot_isr : \n");uart_bus->read(my_test_buf, 16, 100);put_buf(my_test_buf, 16);}if (status == UT_TX) {putchar('T');}
}void user_uart2_send(void *buf, u32 len)
{uart_bus->write(buf, len);
}void user_uart_open(void)
{if (uart_bus) {printf("uart2 already open\n");return;}struct uart_platform_data_t u_arg = {0};u_arg.tx_pin = TCFG_UART2_TX_PORT;u_arg.rx_pin = TCFG_UART2_RX_PORT;u_arg.rx_cbuf = uart_cbuf;u_arg.rx_cbuf_size = sizeof(uart_cbuf);u_arg.frame_length = 16; //起uart_isr_handle中断的数据长度u_arg.rx_timeout = 100;u_arg.isr_cbfun = uart_isr_handle;u_arg.baud = TCFG_UART2_BAUDRATE;u_arg.is_9bit = 0;printf("=========================== user_uart_open() ...\n");uart_bus = uart_dev_open(&u_arg);printf("========================comming %s,%d\n", __func__, __LINE__);if (uart_bus != NULL) {printf("=================success\n");gpio_set_hd(TCFG_UART2_TX_PORT, 1);gpio_set_hd0(TCFG_UART2_TX_PORT, 1);//os_task_create(uart_u_task, (void *)uart_bus, 31, 512, 0, "uart_u_task");} else {printf("=========================Uart open false\n");}
}void user_uart_close(void)
{printf("=========================== user_uart_close() ...\n");if (uart_bus != NULL) {uart_dev_close(uart_bus);uart_bus = NULL;}
}