龙芯1c库是把龙芯1c的常用外设的常用功能封装为一个库,类似于STM32库。本文先讲解了龙芯1c库中的串口相关的函数,然后是如何利用这些函数实现串口通信。比如在串口打印helloworld,实现串口echo(即收到什么原封不动的发送回去),如何实现printf。再后是简单介绍一下龙芯1c的串口,最后是讨论一下串口相关的接口函数时如何封装的。
龙芯1c库的git地址是https://gitee.com/caogos/OpenLoongsonLib1c
龙芯1c库中串口接口使用示例
串口接口简介
先来看下串口头文件中提供哪些函数,头文件ls1c_uart.h源码如下
// 串口相关头文件
#ifndef __OPENLOONGSON_UART_H
#define __OPENLOONGSON_UART_H
// 串口模块编号
typedef enum
{
LS1C_UART00 = 0, // 全功能串口UART0可以分为两个四线串口UART00和UART01
LS1C_UART01,
LS1C_UART1,
LS1C_UART2,
LS1C_UART3,
LS1C_UART4,
LS1C_UART5,
LS1C_UART6,
LS1C_UART7,
LS1C_UART8,
LS1C_UART9,
LS1C_UART10,
LS1C_UART11
}ls1c_uart_t;
// 串口信息
typedef struct
{
ls1c_uart_t UARTx; // 串口模块编号
unsigned int baudrate; // 波特率
BOOL rx_enable; // 是否需要使用串口接收数据(使能接收中断),发送默认使能
}ls1c_uart_info_t;
/*
* 获取指定串口模块的基地址
* @UARTx 串口编号
* @ret 基地址
*/
inline void *uart_get_base(ls1c_uart_t UARTx);
/*
* 初始化指定的串口模块
* @uart_info_p 串口模块信息
*/
void uart_init(ls1c_uart_info_t *uart_info_p);
/*
* 初始化串口2
*/
void uart2_init(void);
/*
* 在串口2上打印字符串
* @str 待打印的字符串
*/
void uart2_print(const char *str);
/*
* 在调试串口打印字符串
* @str 待打印的字符串
*/
void uart_debug_print(const char *str);
/*
* 在调试串口打印一个字符
* @ch 待打印的字符
*/
void uart_debug_putc(unsigned char ch);
/*
* 把中断号转换为串口号
* @IRQn 中断号
* @ret 串口号
*/
inline ls1c_uart_t uart_irqn_to_uartx(int IRQn);
/*
* 发送一个字节
* @uartx 串口号
* @ch 待发送的字符串
*/
void uart_putc(ls1c_uart_t uartx, unsigned char ch);
/*
* 打印一个字符串到指定串口
* @uartx 串口号
* @str 待打印的字符串
*/
void uart_print(ls1c_uart_t uartx, const char *str);
#endif
一般来说,只需要先调用uart_init()对指定串口初始化,并调用函数pin_set_remap()设置引脚复用,然后即可调用uart_putc()或者uart_print()发送。如果需要接收数据的话,需要调用irq_install()设置中断处理函数,并调用irq_enable()使能相应中断。最后实现中断处理函数即可。
因为我使用的板子是把串口2作为调试串口的,所以头文件中还出现了几个串口2相关的函数。
测试用例
为了进一步演示如何使用这些接口函数,设计了以下几个测试用例。
在串口上打印helloworld
这里以调试串口2为例,在串口2上打印helloworld。代码不多,这里直接贴代码
/*
* 初始化串口2
*/
void uart2_init(void)
{
unsigned int tx_gpio = 37;
unsigned int rx_gpio = 36;
// 设置复用
pin_set_remap(tx_gpio, PIN_REMAP_SECOND);
pin_set_remap(rx_gpio, PIN_REMAP_SECOND);
// 初始化相关寄存器
debug_uart_info.UARTx = LS1C_UART2;
debug_uart_info.baudrate = 115200;
debug_uart_info.rx_enable = FALSE; // 调试串口只需要打印(发送)功能,不需要接收功能
uart_init(&debug_uart_info);
return ;
}
// 通过串口2打印helloworld
void test_uart2_print_helloworld(void)
{
while (1)
{
uart2_print("hello world!\r\n");
delay_s(1);
}
}
运行结果如下
函数printf()
前面已经用函数uart2_print()打印了helloworld,函数printf()也可以打印字符串。那么函数uart2_print和printf()有什么异同?函数uart2_print()只有一个入参,入参是什么样打印出来的字符串就是什么样;而printf()可以有多个参数,入参可以直接是一个字符串,也可以是一个格式,然后后面跟各种参数,printf()内部会将这些参数按照指定的格式生成字符串,并打印出来。实际上,printf()内部最后会调用函数uart2_print()把格式化生成的字符串打印出来。函数printf()使用起来更灵活,一般都是使用函数printf()。
函数printf()