阅读量:0
1、串口屏界面设计
1.新建工程
保存位置自定义,作为一个合格的嵌入式工程师要有路径下没有中文的情况并命名。
选择自己串口屏对应的芯片,一般屏幕背面会有,也可以查看资料。
选择显示方向,自行选择。按照自己的爱好
右边可对当前页面重命名。
再进行一些基础代码修改。一般情况下修改波特率与单片机串口一致即可。
Program.s
//以下代码只在上电时运行一次,一般用于全局变量定义和上电初始化数据 int sys0=0,sys1=0,sys2=0 //全局变量定义目前仅支持4字节有符号整形(int),不支持其他类型的全局变量声明,如需使用字符串类型可以在页面中使用变量控件 bauds=115200 //配置波特率为115200 dim=100 //配置亮度100 bkcmd=0 printh 00 00 00 ff ff ff 88 ff ff ff//输出上电信息到串口 page 0 //上电刷新第0页
然后从工具箱添加组件
右下角可进行属性设置。
然后在按钮组件添加弹起事件,0 1 2 3类似,依次添加。
串口屏界面设计完毕,下载到串口屏。
接下来进行单片机程序编写,本实验使用串口1与串口屏通讯。
程序与串口驱动无异
tjc_usart_hmi.h
#ifndef __TJCUSARTHMI_H_ #define __TJCUSARTHMI_H_ #include "stm32f10x.h" /** 打印到屏幕串口 */ void TJCPrintf (const char *str, ...); void initRingBuff(void); void writeRingBuff(uint8_t data); void deleteRingBuff(uint16_t size); uint16_t getRingBuffLenght(void); uint8_t read1BFromRingBuff(uint16_t position); void USART1_Init(uint32_t bound); void USART1_printf(char* fmt,...); //串口1的专用printf函数 #define RINGBUFF_LEN (500) //定义最大接收字节数 500 #define usize getRingBuffLenght() #define code_c() initRingBuff() #define udelete(x) deleteRingBuff(x) #define u(x) read1BFromRingBuff(x) extern uint8_t RxBuff[1]; #endif
tjc_usart_hmi.c
#include <stdint.h> #include <stdio.h> #include <string.h> #include <stdarg.h> #include "tjc_usart_hmi.h" #include <stddef.h> #include <stm32f10x_usart.h> #define STR_LENGTH 100 typedef struct { uint16_t Head; uint16_t Tail; uint16_t Lenght; uint8_t Ring_data[RINGBUFF_LEN]; }RingBuff_t; RingBuff_t ringBuff; //创建一个ringBuff的缓冲区 uint8_t RxBuff[1]; void TJCPrintf (const char *str, ...){ char buffer[STR_LENGTH+1]; // 数据长度 u8 i = 0; va_list arg_ptr; va_start(arg_ptr, str); vsnprintf(buffer, STR_LENGTH+1, str, arg_ptr); va_end(arg_ptr); while ((i < STR_LENGTH) && (i < strlen(buffer))) { USART_SendData(USART1, (u8) buffer[i++]); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); } USART_SendData(USART1,(uint8_t)0xff); //这个函数改为你的单片机的串口发送单字节函数 while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1,(uint8_t)0xff); //这个函数改为你的单片机的串口发送单字节函数 while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1,(uint8_t)0xff); //这个函数改为你的单片机的串口发送单字节函数 while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); } /******************************************************** 函数名: USART1_IRQHandler 作者: 日期: 2022.10.08 功能: 串口接收中断,将接收到的数据写入环形缓冲区 输入参数: 返回值: void 修改记录: **********************************************************/ void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_RXNE); RxBuff[0] = USART_ReceiveData(USART1); writeRingBuff(RxBuff[0]); } } /******************************************************** 函数名: initRingBuff 作者: 日期: 2022.10.08 功能: 初始化环形缓冲区 输入参数: 返回值: void 修改记录: **********************************************************/ void initRingBuff(void) { //初始化相关信息 ringBuff.Head = 0; ringBuff.Tail = 0; ringBuff.Lenght = 0; } /******************************************************** 函数名: writeRingBuff 作者: 日期: 2022.10.08 功能: 往环形缓冲区写入数据 输入参数: 返回值: void 修改记录: **********************************************************/ void writeRingBuff(uint8_t data) { if(ringBuff.Lenght >= RINGBUFF_LEN) //判断缓冲区是否已满 { return ; } ringBuff.Ring_data[ringBuff.Tail]=data; ringBuff.Tail = (ringBuff.Tail+1)%RINGBUFF_LEN;//防止越界非法访问 ringBuff.Lenght++; } /******************************************************** 函数名: deleteRingBuff 作者: 日期: 2022.10.08 功能: 删除串口缓冲区中相应长度的数据 输入参数: 要删除的长度 返回值: void 修改记录: **********************************************************/ void deleteRingBuff(uint16_t size) { if(size >= ringBuff.Lenght) { initRingBuff(); return; } for(int i = 0; i < size; i++) { if(ringBuff.Lenght == 0)//判断非空 { initRingBuff(); return; } ringBuff.Head = (ringBuff.Head+1)%RINGBUFF_LEN;//防止越界非法访问 ringBuff.Lenght--; } } /******************************************************** 函数名: read1BFromRingBuff 作者: 日期: 2022.10.08 功能: 从串口缓冲区读取1字节数据 输入参数: position:读取的位置 返回值: 所在位置的数据(1字节) 修改记录: **********************************************************/ uint8_t read1BFromRingBuff(uint16_t position) { uint16_t realPosition = (ringBuff.Head + position) % RINGBUFF_LEN; return ringBuff.Ring_data[realPosition]; } /******************************************************** 函数名: getRingBuffLenght 作者: 日期: 2022.10.08 功能: 获取串口缓冲区的数据数量 输入参数: 返回值: 串口缓冲区的数据数量 修改记录: **********************************************************/ uint16_t getRingBuffLenght() { return ringBuff.Lenght; } /******************************************************** 函数名: isRingBuffOverflow 作者: 日期: 2022.10.08 功能: 判断环形缓冲区是否已满 输入参数: 返回值: 1:环形缓冲区已满 , 2:环形缓冲区未满 修改记录: **********************************************************/ uint8_t isRingBuffOverflow() { return ringBuff.Lenght == RINGBUFF_LEN; } //初始化IO 串口1 //bound:波特率 void USART1_Init(uint32_t bound){ //串口1初始化并启动 //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 //USART1_TX PA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX PA.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 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(USART1, &USART_InitStructure); //初始化串口 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启ENABLE/关闭DISABLE中断 USART_Cmd(USART1, ENABLE); //使能串口 }
main.c
#include "stm32f10x.h" #include "tjc_usart_hmi.h" #include "stm32f10x_rcc.h" #define FRAMELENGTH 6 void NVIC_Configuration(void); void RCC_Configuration(void); int main(void) { RCC_Configuration(); NVIC_Configuration(); USART1_Init(115200); //串口初始化为115200 TJCPrintf("\x00"); //为确保串口HMI正常通信 while(1) { //stm32f103的GND接串口屏或串口工具的GND,共地 //stm32f103的TX1(PA9)接串口屏或串口工具的RX //stm32f103的RX1(PA10)接串口屏或串口工具的TX //stm32f103的5V接串口屏的5V,如果是串口工具,不用接5V也可以 //串口数据格式: //串口数据帧长度:6字节 //帧头 led编号 LED状态 帧尾 //0x55 1字节 1字节 0xffffff //例子1:上位机代码 printh 55 01 00 ff ff ff 含义:1号led关闭 //例子2:上位机代码 printh 55 04 01 ff ff ff 含义:4号led打开 //例子3:上位机代码 printh 55 00 01 ff ff ff 含义:0号led打开 //例子4:上位机代码 printh 55 04 00 ff ff ff 含义:4号led关闭 while(usize >= FRAMELENGTH) { //校验帧头帧尾是否匹配 if(u(0) != 0x55 || u(3) != 0xff || u(4) != 0xff || u(5) != 0xff) { //不匹配删除1字节 udelete(1); }else { //匹配,跳出循环 break; } } //进行解析 if(usize >= FRAMELENGTH && u(0) == 0x55 && u(3) == 0xff && u(4) == 0xff && u(5) == 0xff) { TJCPrintf("msg.txt=\"led %d is %s\"", u(1), u(2) ? "on" : "off"); udelete(FRAMELENGTH); } //delay_ms(1000); } } void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* 嵌套向量中断控制器组选择 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 配置USART为中断源 */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; /* 抢断优先级*/ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; /* 子优先级 */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; /* 使能中断 */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* 初始化配置NVIC */ NVIC_Init(&NVIC_InitStructure); } void RCC_Configuration(void){ //RCC时钟的设置 ErrorStatus HSEStartUpStatus; RCC_DeInit(); /* RCC system reset(for debug purpose) RCC寄存器恢复初始化值*/ RCC_HSEConfig(RCC_HSE_ON); /* Enable HSE 使能外部高速晶振*/ HSEStartUpStatus = RCC_WaitForHSEStartUp(); /* Wait till HSE is ready 等待外部高速晶振使能完成*/ if(HSEStartUpStatus == SUCCESS){ /*设置PLL时钟源及倍频系数*/ RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //RCC_PLLMul_x(枚举2~16)是倍频值。当HSE=8MHZ,RCC_PLLMul_9时PLLCLK=72MHZ /*设置AHB时钟(HCLK)*/ RCC_HCLKConfig(RCC_SYSCLK_Div1); //RCC_SYSCLK_Div1——AHB时钟 = 系统时钟(SYSCLK) = 72MHZ(外部晶振8HMZ) /*注意此处的设置,如果使用SYSTICK做延时程序,此时SYSTICK(Cortex System timer)=HCLK/8=9MHZ*/ RCC_PCLK1Config(RCC_HCLK_Div2); //设置低速AHB时钟(PCLK1),RCC_HCLK_Div2——APB1时钟 = HCLK/2 = 36MHZ(外部晶振8HMZ) RCC_PCLK2Config(RCC_HCLK_Div1); //设置高速AHB时钟(PCLK2),RCC_HCLK_Div1——APB2时钟 = HCLK = 72MHZ(外部晶振8HMZ) /*注:AHB主要负责外部存储器时钟。APB2负责AD,I/O,高级TIM,串口1。APB1负责DA,USB,SPI,I2C,CAN,串口2,3,4,5,普通TIM */ FLASH_SetLatency(FLASH_Latency_2); //设置FLASH存储器延时时钟周期数 /*FLASH时序延迟几个周期,等待总线同步操作。 推荐按照单片机系统运行频率: 0—24MHz时,取Latency_0; 24—48MHz时,取Latency_1; 48~72MHz时,取Latency_2*/ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //选择FLASH预取指缓存的模式,预取指缓存使能 RCC_PLLCmd(ENABLE); //使能PLL while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET); //等待PLL输出稳定 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //选择SYSCLK时钟源为PLL while(RCC_GetSYSCLKSource() != 0x08); //等待PLL成为SYSCLK时钟源 }
代码很好理解,查看注释可知,可根据自己情况添加控制外设以及显示温湿度等函数