4.APP软件设计
移动终端APP第一次打开后进行手动配网,当搜索到指定的WIFI信号时进行连接,随后对TCP端口进行监听,对接受的数据包进行解析,随后将数据显示在屏幕上。
5.上位机软件设计
上位机软件基于JAVA进行设计,通过端口接收测量终端传输的数据包,并进行解析,通过图形形象地展示出心率的实时状态。
【RTT使用简介】
本部分简单介绍了本系统中使用OLED和WIFI模块所涉及的SPI和串口通信在RTT中的使用过程,对函数的调用过程、关键函数的使用、设备驱动的调用分别进行了一些介绍。
1.OLED
OLED与芯片的通过SPI协议通信,设备驱动使用流程大致如下:
(1)定义设备对象,调用 rt_spi_bus_attach_device() 挂载设备到SPI总线
rt_err_t rt_spi_bus_attach_device(struct rt_spi_device *device,
const char *name,
const char *bus_name,
void *user_data)
此函数用于挂载一个SPI设备到指定的SPI总线,向内核注册SPI设备,并将user_data保存到SPI设备device里。
[tr]参数描述[/tr]
deviceSPI设备句柄
nameSPI设备名称
bus_nameSPI总线名称
user_data用户数据指针
a. 首先需要定义好SPI设备对象device
b. SPI总线命名原则为spix, SPI设备命名原则为spixy,本项目的spi10 表示挂载在在 spi1设备。
c. SPI总线名称可以在msh shell输入list_device 命令查看,确定SPI设备要挂载的SPI总线。
d. user_data一般为SPI设备的CS引脚指针,进行数据传输时SPI控制器会操作此引脚进行片选。
本项目的底层驱动 drv_ssd1306.c 中 rt_hw_ssd1306_config() 挂载ssd1306设备到SPI总线源码如下:
#define SPI_BUS_NAME “spi1” /* SPI总线名称 */#define SPI_SSD1306_DEVICE_NAME “spi10” /* SPI设备名称 */static struct rt_spi_device spi_dev_ssd1306; /* SPI设备ssd1306对象 */static struct stm32_hw_spi_cs spi_cs; /* SPI设备CS片选引脚 */static int rt_hw_ssd1306_config(void){
rt_err_t res;
/* oled use PC8 as CS */
spi_cs.pin = CS_PIN;
rt_pin_mode(spi_cs.pin, PIN_MODE_OUTPUT); /* 设置片选管脚模式为输出 */res=rt_spi_bus_attach_device(&spi_dev_ssd1306,SPI_SSD1306_DEVICE_NAME, SPI_BUS_NAME, (void*)&spi_cs);if (res != RT_EOK){
OLED_TRACE(“rt_spi_bus_attach_device!rn”);
return res;}}
(2)调用 rt_spi_configure() 配置SPI总线模式。
挂载SPI设备到SPI总线后,为满足不同设备的时钟、数据宽度等要求,通常需要配置SPI模式、频率参数SPI从设备的模式决定主设备的模式,所以SPI主设备的模式必须和从设备一样两者才能正常通讯。
rt_err_t rt_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg) [tr]参数描述[/tr]
deviceSPI设备句柄
cfgSPI传输配置参数指针
此函数会保存cfg指向的模式参数到device里,当device调用数据传输函数时都会使用此配置信息。
挂载SPI设备到SPI总线后必须使用此函数配置SPI设备的传输参数。
本项目底层驱动 drv_ssd1306.c 中 rt_hw_ssd1306_config() 配置SPI传输参数源码如下:
static int rt_hw_ssd1306_config(void){
/* config spi */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
cfg.max_hz = 20 * 1000 *1000; /* 20M,SPI max 42MHz,ssd1306 4-wire spi */
rt_spi_configure(&spi_dev_ssd1306, &cfg);
}
(3) 使用 rt_spi_transfer() 等相关数据传输接口传输数据。
SPI设备挂载到SPI总线并配置好相关SPI传输参数后就可以调用RT-Thread提供的一系列SPI设备驱动数据传输函数。
struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device *device,
struct rt_spi_message *message)
此函数可以传输一连串消息,用户可以很灵活的设置message结构体各参数的数值,从而可以很方便的控制数据传输方式。
发送指令和数据的函数源码如下:
rt_err_t ssd1306_write_cmd(const rt_uint8_t cmd){
rt_size_t len;
rt_pin_write(DC_PIN, PIN_LOW); /* 命令低电平 */
len = rt_spi_send(&spi_dev_ssd1306, &cmd, 1);
if (len != 1)
{
OLED_TRACE(“ssd1306_write_cmd error. %drn”,len);
return -RT_ERROR;
}
else
{
return RT_EOK;
}}rt_err_t ssd1306_write_data(const rt_uint8_t data){
rt_size_t len;
rt_pin_write(DC_PIN, PIN_HIGH); /* 数据高电平 */
len = rt_spi_send(&spi_dev_ssd1306, &data, 1);
if (len != 1)
{
OLED_TRACE(“ssd1306_write_data error. %drn”,len);
return -RT_ERROR;
}
else
{
return RT_EOK;
}}
(4)通过设备驱动的调用在OLED上显示图像和文字,首先需要确定信息在OLED上的行列起始地址,调用ssd1306_write_cmd() 向SSD1306发送指令,调用 ssd1306_write_data() 向SSD1306发送数据,源代码如下:
void set_column_address(rt_uint8_t start_address, rt_uint8_t end_address){
ssd1306_write_cmd(0x15); // Set Column Address
ssd1306_write_data(start_address); // Default =》 0x00 (Start Address)
ssd1306_write_data(end_address); // Default =》 0x7F (End Address)}void set_row_address(rt_uint8_t start_address, rt_uint8_t end_address){
ssd1306_write_cmd(0x75); // Set Row Address
ssd1306_write_data(start_address); // Default =》 0x00 (Start Address)
ssd1306_write_data(end_address); // Default =》 0x7F (End Address)}
2.串口
串口用来与WIFI 模块ESP8266进行通信,在串口的使用过程中,主要使用了以下几个函数进行初始化:
static void RCC_Configuration(void)
static void GPIO_Configuration(void)
static void NVIC_Configuration(struct stm32_uart *uart)
void rt_hw_usart_init();
(1)在void rt_hw_usart_init();中对波特率、串口号、字长等进行设置。
实际的路径调用过程如下。
startup.c main()
-→ startup.c rtthread_startup()
-→ board.c rt_hw_board_init()
-→ usart.c rt_hw_usart_init()
(2)为了设备纳入到RTT的IO设备层中,需要为这个设备创建一个名为rt_device的数据结构。
该数据结构在rtdef.h中定义。需要一些函数来操作逻辑设备,这些函数在rt-thread/src/device.c文件中提供,它们是:
rt_err_t rt_device_register(rt_device_t dev, const char *name, rt_uint16_t flags)
将rt_device数据结构加入到RTT的设备层中,这个过程称为“注册”。RTT的设备管理层会为这个数据结构创建唯一的device_id。
rt_err_t rt_device_unregister(rt_device_t dev)
与注册相反,自然是注销了,将某个设备从RTT的设备驱动层中移除。
rt_device_t rt_device_find(const char *name)
根据设备的字符串名查找某个设备。
rt_err_t rt_device_init(rt_device_t dev)
通过调用rt_device数据结构中的init函数来初始设备。
rt_err_t rt_device_init_all(void)
初始化RTT设备管理层中的所有已注册的设备
rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
通过调用rt_device数据结构中的open函数来打开设备。
rt_err_t rt_device_close(rt_device_t dev)
通过调用rt_device数据结构中的close函数来关闭设备。
rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
通过调用rt_device数据结构中的read函数来从设备上读取数据。
rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
通过调用rt_device数据结构中的write函数来向设备写入数据(比如设备是flash,SD卡等,nand or nor flash等等)。
(3)open,read等函数的编写过程如下:
Ⅰ。.init函数完成对设备数据结构的初始化工作。
RTT的设备驱动存在大量的预定义宏,它们在rtdef.h中定义。
static rt_err_t rt_serial_init (rt_device_t dev) { struct stm32_serial_device* uart = (struct stm32_serial_device*) dev-》user_data;
if (!(dev-》flag & RT_DEVICE_FLAG_ACTIVATED))
{
if (dev-》flag & RT_DEVICE_FLAG_INT_RX)
{
rt_memset(uart-》int_rx-》rx_buffer, 0, sizeof(uart-》int_rx-》rx_buffer));
uart-》int_rx-》read_index = 0;
uart-》int_rx-》save_index = 0;
}
/* Enable USART */
USART_Cmd(uart-》uart_device, ENABLE);
dev-》flag |= RT_DEVICE_FLAG_ACTIVATED;
} return RT_EOK; }
Ⅱ.open
因为在usart.c中已经初始usart设备,然后init中通过USART_Cmd语句后,串口就会开始工作。因此open函数设置为空即可
close同colse,之间置空即可
Ⅲ.read
static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
pos表示读写的位置,buffer是用于存储读取到数据的缓冲区。size为字节数目。对于USART这种串行的流设备来说,pos没有意义,因此这里的pos没有意义。rt_device数据结构dev的的 user_data域存放了(struct stm32_serial_device*)型指针。【待修改】如果采用INT_RX模式,即中断接受模式,则主体代码为
while (size)
{
rt_base_t level; /* disable interrupt */
level = rt_hw_interrupt_disable(); if (uart-》int_rx-》read_index != uart-》int_rx-》save_index)
{
/* read a character */
*ptr++ = uart-》int_rx-》rx_buffer[uart-》int_rx-》read_index];
size--; /* move to next position */
uart-》int_rx-》read_index ++;
if (uart-》int_rx-》read_index 》= UART_RX_BUFFER_SIZE)
uart-》int_rx-》read_index = 0;
}
else
{
/* set error code */
err_code = -RT_EEMPTY; /* enable interrupt */
rt_hw_interrupt_enable(level);
break;
} /* enable interrupt */
rt_hw_interrupt_enable(level);
}
Ⅳ.write
向串口写入数据,即发送数据。
/* polling mode */
if (dev-》flag & RT_DEVICE_FLAG_STREAM)
{
/* stream mode */
while (size)
{
if (*ptr == ‘n’)
{
while (!(uart-》uart_device-》SR & USART_FLAG_TXE));
uart-》uart_device-》DR = ‘r’;
/* interrupt mode Tx, does not support */
RT_ASSERT(0);
} while (!(uart-》uart_device-》SR & USART_FLAG_TXE));
uart-》uart_device-》DR = (*ptr & 0x1FF); ++ptr; --size;
}
}
else
{
/* write data directly */
while (size)
{
while (!(uart-》uart_device-》SR & USART_FLAG_TXE));
uart-》uart_device-》DR = (*ptr & 0x1FF); ++ptr; --size;
}
}
Ⅴ.control
static rt_err_t rt_serial_control (rt_device_t dev, rt_uint8_t cmd, void *args)
{
struct stm32_serial_device* uart; RT_ASSERT(dev != RT_NULL); uart = (struct stm32_serial_device*)dev-》user_data;
switch (cmd)
{
case RT_DEVICE_CTRL_SUSPEND:
/* suspend device */
dev-》flag |= RT_DEVICE_FLAG_SUSPENDED;
USART_Cmd(uart-》uart_device, DISABLE);
break; case RT_DEVICE_CTRL_RESUME:
/* resume device */
dev-》flag &= ~RT_DEVICE_FLAG_SUSPENDED;
USART_Cmd(uart-》uart_device, ENABLE);
break;
} return RT_EOK;
}
Ⅶ。注册USART的rt_device结构
rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct stm32_serial_device *serial)
{
RT_ASSERT(device != RT_NULL); if ((flag & RT_DEVICE_FLAG_DMA_RX) ||
(flag & RT_DEVICE_FLAG_INT_TX))
{
RT_ASSERT(0);
} device-》type = RT_Device_Class_Char;
device-》rx_indicate = RT_NULL;
device-》tx_complete = RT_NULL;
device-》init = rt_serial_init;
device-》open = rt_serial_open;
device-》close = rt_serial_close;
device-》read = rt_serial_read;
device-》write = rt_serial_write;
device-》control = rt_serial_control;
device-》user_data = serial; /* register a character device */
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
}
4.APP软件设计
移动终端APP第一次打开后进行手动配网,当搜索到指定的WIFI信号时进行连接,随后对TCP端口进行监听,对接受的数据包进行解析,随后将数据显示在屏幕上。
5.上位机软件设计
上位机软件基于JAVA进行设计,通过端口接收测量终端传输的数据包,并进行解析,通过图形形象地展示出心率的实时状态。
【RTT使用简介】
本部分简单介绍了本系统中使用OLED和WIFI模块所涉及的SPI和串口通信在RTT中的使用过程,对函数的调用过程、关键函数的使用、设备驱动的调用分别进行了一些介绍。
1.OLED
OLED与芯片的通过SPI协议通信,设备驱动使用流程大致如下:
(1)定义设备对象,调用 rt_spi_bus_attach_device() 挂载设备到SPI总线
rt_err_t rt_spi_bus_attach_device(struct rt_spi_device *device,
const char *name,
const char *bus_name,
void *user_data)
此函数用于挂载一个SPI设备到指定的SPI总线,向内核注册SPI设备,并将user_data保存到SPI设备device里。
[tr]参数描述[/tr]
deviceSPI设备句柄
nameSPI设备名称
bus_nameSPI总线名称
user_data用户数据指针
a. 首先需要定义好SPI设备对象device
b. SPI总线命名原则为spix, SPI设备命名原则为spixy,本项目的spi10 表示挂载在在 spi1设备。
c. SPI总线名称可以在msh shell输入list_device 命令查看,确定SPI设备要挂载的SPI总线。
d. user_data一般为SPI设备的CS引脚指针,进行数据传输时SPI控制器会操作此引脚进行片选。
本项目的底层驱动 drv_ssd1306.c 中 rt_hw_ssd1306_config() 挂载ssd1306设备到SPI总线源码如下:
#define SPI_BUS_NAME “spi1” /* SPI总线名称 */#define SPI_SSD1306_DEVICE_NAME “spi10” /* SPI设备名称 */static struct rt_spi_device spi_dev_ssd1306; /* SPI设备ssd1306对象 */static struct stm32_hw_spi_cs spi_cs; /* SPI设备CS片选引脚 */static int rt_hw_ssd1306_config(void){
rt_err_t res;
/* oled use PC8 as CS */
spi_cs.pin = CS_PIN;
rt_pin_mode(spi_cs.pin, PIN_MODE_OUTPUT); /* 设置片选管脚模式为输出 */res=rt_spi_bus_attach_device(&spi_dev_ssd1306,SPI_SSD1306_DEVICE_NAME, SPI_BUS_NAME, (void*)&spi_cs);if (res != RT_EOK){
OLED_TRACE(“rt_spi_bus_attach_device!rn”);
return res;}}
(2)调用 rt_spi_configure() 配置SPI总线模式。
挂载SPI设备到SPI总线后,为满足不同设备的时钟、数据宽度等要求,通常需要配置SPI模式、频率参数SPI从设备的模式决定主设备的模式,所以SPI主设备的模式必须和从设备一样两者才能正常通讯。
rt_err_t rt_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg) [tr]参数描述[/tr]
deviceSPI设备句柄
cfgSPI传输配置参数指针
此函数会保存cfg指向的模式参数到device里,当device调用数据传输函数时都会使用此配置信息。
挂载SPI设备到SPI总线后必须使用此函数配置SPI设备的传输参数。
本项目底层驱动 drv_ssd1306.c 中 rt_hw_ssd1306_config() 配置SPI传输参数源码如下:
static int rt_hw_ssd1306_config(void){
/* config spi */
{
struct rt_spi_configuration cfg;
cfg.data_width = 8;
cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
cfg.max_hz = 20 * 1000 *1000; /* 20M,SPI max 42MHz,ssd1306 4-wire spi */
rt_spi_configure(&spi_dev_ssd1306, &cfg);
}
(3) 使用 rt_spi_transfer() 等相关数据传输接口传输数据。
SPI设备挂载到SPI总线并配置好相关SPI传输参数后就可以调用RT-Thread提供的一系列SPI设备驱动数据传输函数。
struct rt_spi_message *rt_spi_transfer_message(struct rt_spi_device *device,
struct rt_spi_message *message)
此函数可以传输一连串消息,用户可以很灵活的设置message结构体各参数的数值,从而可以很方便的控制数据传输方式。
发送指令和数据的函数源码如下:
rt_err_t ssd1306_write_cmd(const rt_uint8_t cmd){
rt_size_t len;
rt_pin_write(DC_PIN, PIN_LOW); /* 命令低电平 */
len = rt_spi_send(&spi_dev_ssd1306, &cmd, 1);
if (len != 1)
{
OLED_TRACE(“ssd1306_write_cmd error. %drn”,len);
return -RT_ERROR;
}
else
{
return RT_EOK;
}}rt_err_t ssd1306_write_data(const rt_uint8_t data){
rt_size_t len;
rt_pin_write(DC_PIN, PIN_HIGH); /* 数据高电平 */
len = rt_spi_send(&spi_dev_ssd1306, &data, 1);
if (len != 1)
{
OLED_TRACE(“ssd1306_write_data error. %drn”,len);
return -RT_ERROR;
}
else
{
return RT_EOK;
}}
(4)通过设备驱动的调用在OLED上显示图像和文字,首先需要确定信息在OLED上的行列起始地址,调用ssd1306_write_cmd() 向SSD1306发送指令,调用 ssd1306_write_data() 向SSD1306发送数据,源代码如下:
void set_column_address(rt_uint8_t start_address, rt_uint8_t end_address){
ssd1306_write_cmd(0x15); // Set Column Address
ssd1306_write_data(start_address); // Default =》 0x00 (Start Address)
ssd1306_write_data(end_address); // Default =》 0x7F (End Address)}void set_row_address(rt_uint8_t start_address, rt_uint8_t end_address){
ssd1306_write_cmd(0x75); // Set Row Address
ssd1306_write_data(start_address); // Default =》 0x00 (Start Address)
ssd1306_write_data(end_address); // Default =》 0x7F (End Address)}
2.串口
串口用来与WIFI 模块ESP8266进行通信,在串口的使用过程中,主要使用了以下几个函数进行初始化:
static void RCC_Configuration(void)
static void GPIO_Configuration(void)
static void NVIC_Configuration(struct stm32_uart *uart)
void rt_hw_usart_init();
(1)在void rt_hw_usart_init();中对波特率、串口号、字长等进行设置。
实际的路径调用过程如下。
startup.c main()
-→ startup.c rtthread_startup()
-→ board.c rt_hw_board_init()
-→ usart.c rt_hw_usart_init()
(2)为了设备纳入到RTT的IO设备层中,需要为这个设备创建一个名为rt_device的数据结构。
该数据结构在rtdef.h中定义。需要一些函数来操作逻辑设备,这些函数在rt-thread/src/device.c文件中提供,它们是:
rt_err_t rt_device_register(rt_device_t dev, const char *name, rt_uint16_t flags)
将rt_device数据结构加入到RTT的设备层中,这个过程称为“注册”。RTT的设备管理层会为这个数据结构创建唯一的device_id。
rt_err_t rt_device_unregister(rt_device_t dev)
与注册相反,自然是注销了,将某个设备从RTT的设备驱动层中移除。
rt_device_t rt_device_find(const char *name)
根据设备的字符串名查找某个设备。
rt_err_t rt_device_init(rt_device_t dev)
通过调用rt_device数据结构中的init函数来初始设备。
rt_err_t rt_device_init_all(void)
初始化RTT设备管理层中的所有已注册的设备
rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
通过调用rt_device数据结构中的open函数来打开设备。
rt_err_t rt_device_close(rt_device_t dev)
通过调用rt_device数据结构中的close函数来关闭设备。
rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
通过调用rt_device数据结构中的read函数来从设备上读取数据。
rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
通过调用rt_device数据结构中的write函数来向设备写入数据(比如设备是flash,SD卡等,nand or nor flash等等)。
(3)open,read等函数的编写过程如下:
Ⅰ。.init函数完成对设备数据结构的初始化工作。
RTT的设备驱动存在大量的预定义宏,它们在rtdef.h中定义。
static rt_err_t rt_serial_init (rt_device_t dev) { struct stm32_serial_device* uart = (struct stm32_serial_device*) dev-》user_data;
if (!(dev-》flag & RT_DEVICE_FLAG_ACTIVATED))
{
if (dev-》flag & RT_DEVICE_FLAG_INT_RX)
{
rt_memset(uart-》int_rx-》rx_buffer, 0, sizeof(uart-》int_rx-》rx_buffer));
uart-》int_rx-》read_index = 0;
uart-》int_rx-》save_index = 0;
}
/* Enable USART */
USART_Cmd(uart-》uart_device, ENABLE);
dev-》flag |= RT_DEVICE_FLAG_ACTIVATED;
} return RT_EOK; }
Ⅱ.open
因为在usart.c中已经初始usart设备,然后init中通过USART_Cmd语句后,串口就会开始工作。因此open函数设置为空即可
close同colse,之间置空即可
Ⅲ.read
static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
pos表示读写的位置,buffer是用于存储读取到数据的缓冲区。size为字节数目。对于USART这种串行的流设备来说,pos没有意义,因此这里的pos没有意义。rt_device数据结构dev的的 user_data域存放了(struct stm32_serial_device*)型指针。【待修改】如果采用INT_RX模式,即中断接受模式,则主体代码为
while (size)
{
rt_base_t level; /* disable interrupt */
level = rt_hw_interrupt_disable(); if (uart-》int_rx-》read_index != uart-》int_rx-》save_index)
{
/* read a character */
*ptr++ = uart-》int_rx-》rx_buffer[uart-》int_rx-》read_index];
size--; /* move to next position */
uart-》int_rx-》read_index ++;
if (uart-》int_rx-》read_index 》= UART_RX_BUFFER_SIZE)
uart-》int_rx-》read_index = 0;
}
else
{
/* set error code */
err_code = -RT_EEMPTY; /* enable interrupt */
rt_hw_interrupt_enable(level);
break;
} /* enable interrupt */
rt_hw_interrupt_enable(level);
}
Ⅳ.write
向串口写入数据,即发送数据。
/* polling mode */
if (dev-》flag & RT_DEVICE_FLAG_STREAM)
{
/* stream mode */
while (size)
{
if (*ptr == ‘n’)
{
while (!(uart-》uart_device-》SR & USART_FLAG_TXE));
uart-》uart_device-》DR = ‘r’;
/* interrupt mode Tx, does not support */
RT_ASSERT(0);
} while (!(uart-》uart_device-》SR & USART_FLAG_TXE));
uart-》uart_device-》DR = (*ptr & 0x1FF); ++ptr; --size;
}
}
else
{
/* write data directly */
while (size)
{
while (!(uart-》uart_device-》SR & USART_FLAG_TXE));
uart-》uart_device-》DR = (*ptr & 0x1FF); ++ptr; --size;
}
}
Ⅴ.control
static rt_err_t rt_serial_control (rt_device_t dev, rt_uint8_t cmd, void *args)
{
struct stm32_serial_device* uart; RT_ASSERT(dev != RT_NULL); uart = (struct stm32_serial_device*)dev-》user_data;
switch (cmd)
{
case RT_DEVICE_CTRL_SUSPEND:
/* suspend device */
dev-》flag |= RT_DEVICE_FLAG_SUSPENDED;
USART_Cmd(uart-》uart_device, DISABLE);
break; case RT_DEVICE_CTRL_RESUME:
/* resume device */
dev-》flag &= ~RT_DEVICE_FLAG_SUSPENDED;
USART_Cmd(uart-》uart_device, ENABLE);
break;
} return RT_EOK;
}
Ⅶ。注册USART的rt_device结构
rt_err_t rt_hw_serial_register(rt_device_t device, const char* name, rt_uint32_t flag, struct stm32_serial_device *serial)
{
RT_ASSERT(device != RT_NULL); if ((flag & RT_DEVICE_FLAG_DMA_RX) ||
(flag & RT_DEVICE_FLAG_INT_TX))
{
RT_ASSERT(0);
} device-》type = RT_Device_Class_Char;
device-》rx_indicate = RT_NULL;
device-》tx_complete = RT_NULL;
device-》init = rt_serial_init;
device-》open = rt_serial_open;
device-》close = rt_serial_close;
device-》read = rt_serial_read;
device-》write = rt_serial_write;
device-》control = rt_serial_control;
device-》user_data = serial; /* register a character device */
return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
}
举报