STM32F103学习笔记(5)—— 大彩屏使用——串口通信工程级应用
1.大彩屏概览使用大彩屏的好处是,屏幕操作可以直接用屏幕内部指令,比如禁用按键、文本输出等功能,不需要通过下位机获取指令。对外发送的就只有信号,如停止信号、启动信号等,我们只需要知道一个启动或停止信号就可以了,而不需要发送相应的禁用按键指令,这在迪文屏中是无法实现的如图所示,大彩自家的组屏软件TFT,这里我目前只做了工程画面,没有做音频和视频2.大彩教程如图,可以直接百度大彩屏搜索大彩官网,去官网
目录
1. 大彩屏概览
使用大彩屏的好处是,屏幕操作可以直接用屏幕内部指令,比如禁用按键、文本输出等功能,不需要通过下位机获取指令。
对外发送的就只有信号,如停止信号、启动信号等,我们只需要知道一个启动或停止信号就可以了,而不需要发送相应的禁用按键指令,这在迪文屏中是无法实现的
如图所示,大彩自家的组屏软件TFT,这里我目前只做了工程画面,没有做音频和视频
2. 大彩教程
如图,可以直接百度大彩屏搜索大彩官网,去官网下载资料
3. 指令相关
组屏相关比较简单,看下入门手册自己试试就会了,这里不再多说。主要说一下我在使用过程中遇到的问题。
如下图所示,大彩自带指令系统,在按键触发时候会自动使用串口对外发送指令,因此几乎不需要自己制定对外指令。
点击按键,右侧的对内指令,如下图想要实现点击启动按钮后禁用除停止外其他按键。设置启动的对内指令即可。
波特率设置
最开始一直收不到指令,但是有中断,以为是屏幕坏了,发送的都是00 00 00,然后直接用USB转串口,就是下图这玩意儿
连上之后发现串口助手收到的也是00 00 00,突然想到波特率,因为记得在屏幕上面点了设置是115200,如下图
然后想到每次用屏幕仿真好像都是9600
所以直接把串口助手的波特率设置为9600,发现接收到真实数据。。。原来是波特率没设置好哈哈
实际上他的波特率设置在这里
或者直接点击左边的工程画面
就会出现下图所示,选择115200就可以了
4 . 指令设置
在上面步骤中得到如下界面,点击指令助手
比如使用禁用按键功能,选择如下禁使能控件,选择画面ID、控件ID指定当前想要禁用的按键,然后点击禁用控件即可生成相应指令,将该指令复制粘贴放到上图的按下指令当中。
按下指令可以设置多个,因此可以通过这个来禁用多个按键。
5. 屏幕仿真
如图,点击左上角的小三角开启仿真,模拟真实屏幕发送指令,如图是一个启动和停止的指令。
按下和弹起是两个指令,本次操作我只按下,因此只有按下指令,这个指令是对外发送的,也就是通过串口对外部主板发送的指令。
从图中可以看到只有三条指令,第一条是开始键按下的指令,第二条是停止键按下的指令,第三条是停止键弹起的指令。
因为设置了停止键的触发模式为瞬间,因此在按下的同一时间会自动弹起,而开始键设置的是开关,因此按下之后再次按下才会弹起。
6. 屏幕串口
如图,屏幕与主板之间只需要使用4根线,VCC5v,GND,Dout,Din。
VCC可以直接接入正点原子精英板5V输出口,但是使用电脑USB供电不足5V,因此要用上随主板附带的电源线,接上即可点亮屏幕。屏幕使用只需电源线连接就可以了吗,但是同行需要和主板共地,因此如果使用外接电源,需要把外接电源的地线和主板地线相连。
屏幕后的Dout对应主板RX口,Din对应主板TX口,屏幕和主板间的通信就是通过这个实现的,每次触发屏幕的对外指令就是通过这个发送,而屏幕也可以直接通过这个接收指令。大家可以试试主板接收到开启指令后发送禁用其他按键指令,看看屏幕的状态。
7. 串口设置
如上图所示,我使用了PB10和PB11也就是USART3作为屏幕和主板的通信通道
串口3的代码如下
#include "sys.h"
#include "usart.h"
#include "led.h"
#if 1 //如果使能了接收
//串口1中断服务程序
u8 USART_RX_BUF[30]; //接收缓冲
u8 USART_RX_STA=0;
u8 Lock4UsartRX=0;
u8 Tag;
void uart_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
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(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
USART_Cmd(USART3, ENABLE);
}
void USART3_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
// if(Lock4UsartRX==0
if(1)
{
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART3,USART_IT_RXNE); /* 清中断标志 */
Res = USART_ReceiveData(USART3); //读取接收到的数据
if(USART_RX_STA!=4)//下位机发送结束,开始接收数据
{
USART_RX_BUF[Tag]=Res ;
Tag++;
if(Res==0xFF&&USART_RX_STA==0)
{
USART_RX_STA=1;
}
else if(Res==0xFC&&USART_RX_STA==1)
{
USART_RX_STA=2;
}
else if(Res==0xFF&&USART_RX_STA==2)
{
USART_RX_STA=3;
}
else if(Res==0xFF&&USART_RX_STA==3)
{
USART_RX_STA=4;
Tag=0;
Lock4UsartRX=1;
}
else
{
USART_RX_STA=0;
}
if(Tag>30)
Tag=0;//接收数据错误,重新开始接收...
}
}
}
}
#endif
因为屏幕对外发送的指令都是以FF FC FF FF结尾,因此只要判断最后收到的4个字节是不是这四个字,是的话就关闭接收,然后主函数里面处理这个指令,处理完之后就重新打开接收。(其实如果直接在接收完成后把缓冲区内容直接放到另一个数组里面应该会更好点,这样就可以边接收边处理上一帧的指令,这里我是担心如果在处理的时候缓冲区内容被改变,因此使用上锁来关闭接收中断)
所谓的上锁,如下图所示,给一个标志位,接收完成置4,处理完成再置零。
如下图的接收完成也是有操作的,把判断都放在前面,如果前面的都成立就会跳过else,如果有一个不成立,则都会把USART_RX_STA置零。
8. 按键控制PWM大小
如下图,点上升和下降的发送的指令中,1-9是14位指令,而11到99是15位指令,100是16位指令。
这里我设置的最大是100,因此无需考虑100以上的情况。
先判断是否已经接收完成,如果接收完成则开始处理缓冲区内容。
如果符合以下条件则计算出传过来的数据大小,注意大彩的屏幕发送的数字指令是以3x开头的,如9则是0x39,要去掉3则0x39-16*3即可。如果是0x39 0x39这样的数,则(0x39-16*3)*10+0x39-16*3就可以得到结果99
if(Lock4UsartRX==1) //设置PWM
{
if(USART_RX_BUF[15]!=0x00&&USART_RX_BUF[4]==0x01&&USART_RX_BUF[6]==0x04)
{
pwmNum=100;
}
else if(USART_RX_BUF[14]!=0x00&&USART_RX_BUF[4]==0x01&&USART_RX_BUF[6]==0x04)
{
pwmNum=(USART_RX_BUF[8]-16*3)*10+(USART_RX_BUF[9]-16*3);
}
else if(USART_RX_BUF[13]!=0x00&&USART_RX_BUF[4]==0x01&&USART_RX_BUF[6]==0x04)
{
pwmNum=USART_RX_BUF[8]-16*3;
}
TIM_SetCompare2(TIM3,pwmNum*3); //设置红蓝光PWM
USART_RX_BUF[15]=USART_RX_BUF[14]=USART_RX_BUF[13]=0;
Lock4UsartRX=0;
USART_RX_STA=0;
}
CSDN不能传视屏,我就直接整了个仿真结果给大家伙儿瞅瞅
按理说缓冲区数据8 9应该是本次发送的数据,不知道为什么在处理完之后就直接给置0置1了,后面有时间再看看吧(▼ヘ▼#)....
然后用这个值设置PWM就不用说了吧,不明白的同学可以看看我前面的PWM相关文章。
9. 全部代码
usart.h
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
void uart_init(u32 bound);
#endif
usart.c
#include "sys.h"
#include "usart.h"
#include "led.h"
#if 1 //如果使能了接收
//串口1中断服务程序
u8 USART_RX_BUF[30]; //接收缓冲
u8 USART_RX_STA=0;
u8 Lock4UsartRX=0;
u8 Tag;
void uart_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
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(USART3, &USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
USART_Cmd(USART3, ENABLE);
}
void USART3_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
// if(Lock4UsartRX==0
if(1)
{
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART3,USART_IT_RXNE); /* 清中断标志 */
Res = USART_ReceiveData(USART3); //读取接收到的数据
if(USART_RX_STA!=4)//下位机发送结束,开始接收数据
{
USART_RX_BUF[Tag]=Res ;
Tag++;
if(Res==0xFF&&USART_RX_STA==0)
{
USART_RX_STA=1;
}
else if(Res==0xFC&&USART_RX_STA==1)
{
USART_RX_STA=2;
}
else if(Res==0xFF&&USART_RX_STA==2)
{
USART_RX_STA=3;
}
else if(Res==0xFF&&USART_RX_STA==3)
{
USART_RX_STA=4;
Tag=0;
Lock4UsartRX=1;
}
else
{
USART_RX_STA=0;
}
if(Tag>30)
Tag=0;//接收数据错误,重新开始接收...
}
}
}
}
#endif
mian.c
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "pwm.h"
#include "usart.h"
#include "timer.h"
#include "disPlay.h"
int main(void)
{
delay_init();
ledInit();
uart_init(115200);
TIM2_Int_Init(7999,8999);
TIM3_CH2_PWM_Init(899,0);
while(1)
{
disPlayCommand();
}
}
时间原因,多余的代码没有删掉,请同志们自己删一下。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)