Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
GD32
串口
串口发送函数解析 -- 关于流模式
发布于 2022-08-11 17:42:55 浏览:1164
订阅该版
问题 Q1、在使用GD32F303的官方移植的开发板的例程代码的时候,串口发送能不能使用中断和DMA方式进行发送,和流模式有什么区别? 回答:在该模式下并不支持中断和DMA的方式发送数据,实际在发送过程中,都是以流模式进行数据发送的。 1、在非中断发送模式下 rt_device_write(hinst->serial, 0, buf, size); 发送函数 device_write(dev, pos, buffer, size);通过调用外设公用组件中的写函数,该函数由下面的定义做出规定#define device_write (dev->write)。 根据下面的结构体,可以定位到dev->write。 ``` struct rt_device { struct rt_object parent; /**< inherit from rt_object */ enum rt_device_class_type type; /**< device type */ rt_uint16_t flag; /**< device flag */ rt_uint16_t open_flag; /**< device open flag */ rt_uint8_t ref_count; /**< reference count */ rt_uint8_t device_id; /**< 0 - 255 */ /* device call back */ rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size); rt_err_t (*tx_complete)(rt_device_t dev, void *buffer); #ifdef RT_USING_DEVICE_OPS const struct rt_device_ops *ops; #else /* common device interface */ rt_err_t (*init) (rt_device_t dev); rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag); rt_err_t (*close) (rt_device_t dev); rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); rt_err_t (*control)(rt_device_t dev, int cmd, void *args); #endif #ifdef RT_USING_POSIX_DEVIO const struct dfs_file_ops *fops; struct rt_wqueue wait_queue; #endif void *user_data; /**< device private data */ void *device_data; /**< device private data */ }; ``` ``` struct rt_serial_device { struct rt_device parent; const struct rt_uart_ops *ops; struct serial_configure config; void *serial_rx; void *serial_tx; }; ``` 在 ``` /* register UART device */ rt_hw_serial_register(uarts[i].serial, uarts[i].device_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, (void *)&uarts[i]); 代码中,进行了如下的初始化过程 device->write = rt_serial_write; 下列代码时串行设备的写指令 static rt_size_t rt_serial_write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size) { struct rt_serial_device *serial; RT_ASSERT(dev != RT_NULL); if (size == 0) return 0; //在设备信息结构体中,dev是rt_serial_device结构体的第一个参数,这样用dev作为地址,就可以找到整个参 //数 serial = (struct rt_serial_device *)dev; //以中断的方式发送数据 if (dev->open_flag & RT_DEVICE_FLAG_INT_TX) { return _serial_int_tx(serial, (const rt_uint8_t *)buffer, size); } //以DMA的方式发送数据 #ifdef RT_SERIAL_USING_DMA else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX) { return _serial_dma_tx(serial, (const rt_uint8_t *)buffer, size); } #endif /* RT_SERIAL_USING_DMA */ //以阻塞的方式发送数据 else { return _serial_poll_tx(serial, (const rt_uint8_t *)buffer, size); } } ``` ``` 一下代码是中断发送代码 rt_inline int _serial_int_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length) { int size; struct rt_serial_tx_fifo *tx; RT_ASSERT(serial != RT_NULL); size = length; tx = (struct rt_serial_tx_fifo*) serial->serial_tx; RT_ASSERT(tx != RT_NULL); while (length) { /* * to be polite with serial console add a line feed * to the carriage return character */ //当数据是流数据的情况下,检测到\n就会自动加入\R if (*data == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)) { if (serial->ops->putc(serial, '\r') == -1) { rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER); continue; } } //通过结构体讲数据映射到输出gd32_putc函数上。 //在这一行会等待发送结束的标志位。 //但是在自己写的串口发送数据的函数中gd32_putc中,不会返回-1,所以不会等待接收完成标志位。 if (serial->ops->putc(serial, *(char*)data) == -1) { rt_completion_wait(&(tx->completion), RT_WAITING_FOREVER); continue; } data ++; length --; } return size - length; } ``` ``` 关于(serial->ops->putc(serial, '\r')的初始化,在下两段代码中实现 static const struct rt_uart_ops gd32_uart_ops = { gd32_configure, gd32_control, gd32_putc, gd32_getc }; ``` ``` int gd32_hw_usart_init(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; int i; for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++) { uarts[i].serial->ops = &gd32_uart_ops; uarts[i].serial->config = config; /* register UART device */ rt_hw_serial_register(uarts[i].serial, uarts[i].device_name, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, (void *)&uarts[i]); } return 0; } ``` ``` //流模式 rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length) { int size; RT_ASSERT(serial != RT_NULL); size = length; while (length) { /* * to be polite with serial console add a line feed * to the carriage return character */ if (*data == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)) { serial->ops->putc(serial, '\r'); } serial->ops->putc(serial, *data); ++ data; -- length; } return size - length; } ``` 需要注意的是,在rt_hw_serial_register函数中,入口参数的类型是struct rt_serial_device,但是device = &(serial->parent);代码中device的类型是rt_device,而实际使用串口组件的时候使用的数据类型是typedef struct rt_device *rt_device_t;这一个。在rt_hw_serial_register函数中,通过device->user_data = data;代码存储了整个设备外设的信息。即用户数据里面存储了整个外设的信息。
3
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
不讲武德的老法师
这家伙很懒,什么也没写!
文章
6
回答
16
被采纳
0
关注TA
发私信
相关文章
1
串口DMA发送数据时,数据被覆盖
2
关于串口DMA模式下rt_device_close问题
3
利用stm32f427实现usb转串口,电脑端什么也没有识别到
4
finsh 控制台 适配 RS 485请大神指点????
5
uart_sample.c 中,读串口设备时偏移量pos要设置为-1而不是0?
6
【结贴】at_device软件包中对串口接收数据缺少判断导致数据接收异常
7
串口无法接受数据,但可以发送
8
串口如何有效的清除掉接收缓冲,而不必一个一个的去读取
9
串口接收使用方式问题
10
雅特力FINSH问题
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
线程
RT-Thread Nano
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
807
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部