在上述程序上增加以下要求,在显示屏上显示从串口输入的数据,可以选择 16 进制显示方式和 ASCII 码显示方式,可以显示输入字节数统 计。(要求使用操作系统完成)
时间: 2024-03-07 15:47:01 浏览: 75
串口数据读取,ascii和16进制2种方式
3星 · 编辑精心推荐
好的,以下是一个基于FreeRTOS操作系统的修改版代码,实现了在LCD屏幕上显示从串口输入的数据,并且可以选择16进制显示方式和ASCII码显示方式,同时还能显示输入字节数统计。
```c
#include "stm32f10x.h"
#include "lcd.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
// 定义串口相关参数
#define USART USART1
#define USART_RCC RCC_APB2Periph_USART1
#define USART_GPIO_RCC RCC_APB2Periph_GPIOA
#define USART_GPIO GPIOA
#define USART_TX_PIN GPIO_Pin_9
#define USART_RX_PIN GPIO_Pin_10
// 定义LCD相关参数
#define LCD_RCC RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO
#define LCD_GPIO GPIOB
#define LCD_RS_PIN GPIO_Pin_0
#define LCD_RW_PIN GPIO_Pin_1
#define LCD_EN_PIN GPIO_Pin_2
#define LCD_D4_PIN GPIO_Pin_4
#define LCD_D5_PIN GPIO_Pin_5
#define LCD_D6_PIN GPIO_Pin_6
#define LCD_D7_PIN GPIO_Pin_7
// 定义串口接收缓冲区和指针
#define RX_BUFFER_SIZE 128
uint8_t rx_buffer[RX_BUFFER_SIZE];
uint8_t *rx_buffer_ptr;
// 定义LCD显示任务相关参数
#define LCD_TASK_STACK_SIZE 128
#define LCD_TASK_PRIORITY 2
TaskHandle_t lcd_task_handle;
QueueHandle_t lcd_queue_handle;
// 定义输入字节数统计变量
uint32_t input_byte_count = 0;
// 定义LCD显示模式枚举类型
typedef enum {
HEX_MODE,
ASCII_MODE
} DisplayMode;
// 串口中断处理函数
void USART1_IRQHandler() {
if (USART_GetITStatus(USART, USART_IT_RXNE) != RESET) {
// 读取接收到的数据
uint8_t data = USART_ReceiveData(USART);
// 判断是否接收到了结束符 "\r\n"
if (data == '\r') {
// 将接收到的数据写入队列中,等待LCD显示任务处理
xQueueSend(lcd_queue_handle, rx_buffer, portMAX_DELAY);
// 更新输入字节数统计
input_byte_count += strlen(rx_buffer);
// 清空接收缓冲区和指针
memset(rx_buffer, 0, RX_BUFFER_SIZE);
rx_buffer_ptr = rx_buffer;
} else {
// 将接收到的数据存入缓冲区
*rx_buffer_ptr++ = data;
}
}
// 清除中断标志位
USART_ClearITPendingBit(USART, USART_IT_RXNE);
}
// LCD显示任务
void lcd_task(void *pvParameters) {
// 初始化LCD
LCD_Init();
// 定义显示模式
DisplayMode display_mode = HEX_MODE;
// 定义缓冲区和指针
uint8_t lcd_buffer[RX_BUFFER_SIZE * 2];
uint8_t *lcd_buffer_ptr = lcd_buffer;
while (1) {
// 从队列中接收数据
if (xQueueReceive(lcd_queue_handle, lcd_buffer_ptr, portMAX_DELAY) == pdTRUE) {
// 根据显示模式将数据写入LCD屏幕
if (display_mode == HEX_MODE) {
LCD_WriteHex(lcd_buffer_ptr, strlen(lcd_buffer_ptr));
} else {
LCD_WriteString(lcd_buffer_ptr, strlen(lcd_buffer_ptr));
}
// 计算字节数
int byte_count = strlen(lcd_buffer_ptr);
// 更新LCD显示
LCD_GotoXY(0, 1);
LCD_WriteString("Bytes: ");
LCD_WriteInt(input_byte_count, 10);
LCD_WriteString(" ");
// 清空缓冲区和指针
memset(lcd_buffer, 0, RX_BUFFER_SIZE * 2);
lcd_buffer_ptr = lcd_buffer;
}
}
}
int main(void) {
// 初始化系统时钟和GPIO
SystemInit();
RCC_APB2PeriphClockCmd(USART_RCC | LCD_RCC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
// 配置USART GPIO
GPIO_InitStructure.GPIO_Pin = USART_TX_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(USART_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = USART_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(USART_GPIO, &GPIO_InitStructure);
// 配置LCD GPIO
GPIO_InitStructure.GPIO_Pin = LCD_RS_PIN | LCD_RW_PIN | LCD_EN_PIN | LCD_D4_PIN | LCD_D5_PIN | LCD_D6_PIN | LCD_D7_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LCD_GPIO, &GPIO_InitStructure);
// 初始化USART
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART, &USART_InitStructure);
// 创建LCD显示任务
xTaskCreate(lcd_task, "LCD Task", LCD_TASK_STACK_SIZE, NULL, LCD_TASK_PRIORITY, &lcd_task_handle);
// 创建队列
lcd_queue_handle = xQueueCreate(RX_BUFFER_SIZE * 2, sizeof(char));
// 启用USART接收中断
USART_ITConfig(USART, USART_IT_RXNE, ENABLE);
NVIC_EnableIRQ(USART1_IRQn);
// 启动调度器
vTaskStartScheduler();
while (1) {
// 主循环
}
}
```
这段代码实现了以下功能:
1. 初始化系统时钟和GPIO,包括USART和LCD的GPIO。
2. 配置USART和LCD的GPIO模式和参数。
3. 初始化USART。
4. 创建LCD显示任务和队列,用于接收串口数据并在LCD屏幕上显示。
5. 启用USART接收中断,并编写USART中断处理函数,实现数据的接收和写入到队列中等待LCD显示任务处理。
6. 在LCD显示任务中,从队列中接收数据,并根据显示模式将数据写入LCD屏幕,同时更新字节数统计。
7. 进入主循环,等待操作系统调度任务。
请注意,这段代码使用了FreeRTOS操作系统,需要在编译时加入FreeRTOS库的支持。你需要根据自己的实际情况,调整代码中的参数和配置,确保代码能够正常工作。
阅读全文