0.96OLED软件实现DMA串口接收数据模拟滚屏效果
实现的滚屏效果是当一屏写满时,则清空从开头接着写,不是上移的滚屏,虽然OLED有滚屏命令,但是会带水平位移效果,并且只能提前写好数据,类似于广告牌循环播放的那种.
首先是为OLED屏划分区域. 我选择显示的字体是6*8大小的,这样可以显示多点内容,(这是最小的尺寸了,我试过4*8,太畸形了) 所以一块屏最多显示大约168个字,然后每行可显示21,共8行
用两个坐标来定位就行.显示的时候遇到回车换行也需要跳到下一行显示
#define DIS_ONE_PAGE_BUF 168 //一页的字数
#define DIS_BUFFER DIS_ONE_PAGE_BUF*8 //一页的字数 size()6*8
void OLED_Screen_Show(void){
unsigned int i,tmp,len;
len=Cal_Recv_Len(OLED_Assistant.OLED_ShowBuf_Last_DLen,OLED_Assistant.OLED_ShowBuf_DLen);
for(i=0;i<len;i++){
tmp=OLED_Screen_Buff[OLED_Assistant.OLED_ShowBuf_RPtr];
if(tmp=='\r'){//换行
OLED_Assistant.OLED_ShowBuf_RPtr+=2;
tmp=Cal_Line_Remain(OLED_Assistant.OLED_Screen_WPtr)+1;
OLED_Assistant.OLED_Screen_WPtr+=tmp;
i+=2;
continue;
}
if(OLED_Assistant.OLED_Screen_WPtr>=DIS_ONE_PAGE_BUF){
OLED_Assistant.OLED_Flush_EN=1;//屏幕写满则刷新
OLED_Assistant.OLED_Screen_WPtr=0;
} if(OLED_Assistant.OLED_Flush_EN){
OLED_Clear();
OLED_Assistant.OLED_Flush_EN=0;
}
Cal_Screen_Axis(OLED_Assistant.OLED_Screen_WPtr,&OLED_Assistant.OLED_X,&OLED_Assistant.OLED_Y);//计算坐标
OLED_ShowChar_6x8_Pos(OLED_Assistant.OLED_X,OLED_Assistant.OLED_Y,tmp);
OLED_Assistant.OLED_Screen_WPtr++;
OLED_Assistant.OLED_ShowBuf_RPtr++;
if(OLED_Assistant.OLED_ShowBuf_RPtr>=DIS_BUFFER){
OLED_Assistant.OLED_ShowBuf_RPtr=0;
}
} }
第二个就是显存大小了,视情况而定,我是在串口空闲中断中把DMA接收的数据复制到显存中的,复制的时候通过显存已有长度来接着存储,当达到最大时,直接置0就行。因为前面的数据都显示过了,覆盖就覆盖了。
void USART2_IRQHandler()
{
if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //接收中断
{
//根据应用来定接收长度,每一次空闲中断,则可以通过DMA_GetCurrDataCounter拿到本次接收数据长度
USART_ReceiveData(USART2);
DMA_Cmd(DMA1_Channel6,DISABLE);/* 关闭接收DMA */
DMA_ClearFlag(DMA1_FLAG_TC6);/* 清除标志位 */
/* 重新设置传输数据长度, 要比真实数据长,防止覆盖*/
udma.Recv_Len=RECV_BUF_SIZE-DMA_GetCurrDataCounter(DMA1_Channel6);
// MemClear(udma.Send_Buffer,SEND_BUF_SIZE);
// MemCopy(udma.Recv_Buffer,udma.Send_Buffer,udma.Recv_Len);
OLED_Assistant.OLED_ShowBuf_Last_DLen=OLED_Assistant.OLED_ShowBuf_DLen;
Copy_To_ShowBuff(udma);
OLED_Assistant.OLED_Write_EN=1;
DMA_SetCurrDataCounter(DMA1_Channel6,RECV_BUF_SIZE);
/* 打开DMA */
DMA_Cmd(DMA1_Channel6,ENABLE);
// DMA_Send_EN=1;
} }
第三个就是对于数据的处理了,关键是要能不定长的接收,并且能不定长的显示,然后什么时候刷新,什么显示接收到的内容,就需要几个控制的变量了
typedef struct{
/*
OLED显存指针:用于定位显存读取位置//此指针非彼指针,只是比喻,下同
OLED显存数据长度:用于数据存储(到达最大值,变为0,直接覆盖)
OLED显存上一次数据长度:用于计算接收的数据长度
OLED屏幕位置指针:用于定位当前显示位置
OLED屏幕位置X坐标 COLUMN
OLED屏幕位置Y坐标 ROW
OLED刷新使能标识
OLED显示内容使能标识
*/
unsigned int OLED_ShowBuf_RPtr;
unsigned int OLED_ShowBuf_DLen;
unsigned int OLED_ShowBuf_Last_DLen;
unsigned int OLED_Screen_WPtr;
unsigned char OLED_X;//column (0-20)
unsigned char OLED_Y;//row (0-7)
unsigned char OLED_Flush_EN;
unsigned char OLED_Write_EN;
}OLED_Show_Handler;
extern OLED_Show_Handler OLED_Assistant;//初始化全为0就可
void Copy_To_ShowBuff(U_DMA udma){//复制DMA接收的串口数据,在空闲中断中调用
unsigned int i;
for(i=0;i<udma.Recv_Len;i++){
OLED_Screen_Buff[OLED_Assistant.OLED_ShowBuf_DLen]=udma.Recv_Buffer[i];//每次接收多少数据就写入多少数据
OLED_Assistant.OLED_ShowBuf_DLen++;
if(OLED_Assistant.OLED_ShowBuf_DLen==DIS_BUFFER){
OLED_Assistant.OLED_ShowBuf_DLen=0; //重新从头开始覆盖写入,因为最前面的内容显示过了,可以覆盖
}
}
}
unsigned char Cal_Line_Remain(unsigned int arg){//计算不足一行的数据的长度,用于换行时增加屏幕指针偏移的
unsigned char remain;
remain=arg-(unsigned char)(arg/20)*20;
remain=20-remain;
return remain;
}
void Cal_Screen_Axis(unsigned int wptr,unsigned char *x,unsigned char *y){//计算需要显示的坐标
*y=(unsigned char)(wptr/20);
*x=wptr-(*y)*20;
}
unsigned int Cal_Recv_Len(unsigned int last_len,unsigned int new_len){//计算接收到的数据长度,用于不定长显示
unsigned int recv_len;
if(new_len>=last_len){ //防止循环接收时的接收指针跑到上一次接收指针前面
recv_len=new_len-last_len;
}
else{
recv_len=(DIS_BUFFER-last_len)+recv_len;
}
return recv_len;
}
0.96OLED软件实现DMA串口接收数据模拟滚屏效果的更多相关文章
- STM32 串口DMA方式接收(转)
STM32 是一款基于ARM Cortex-M3内核的32位MCU,主频最高可达72M.最近因为要在车机上集成TPMS功能, 便开始着手STM32的开发工作,STM32F10x系列共有5个串口(USA ...
- Arduino控制超声波检测与0.96OLED及串口显示
Arduino控制超声波检测与0.96OLED及串口显示代码使用库共享(包括超声波检测与U8glib): 使用元件: 0.96寸 12864 I2C OLED 128x64规格 超声波检测模块 湿度模 ...
- STM32 HAL库使用中断实现串口接收不定长数据
以前用DMA实现接收不定长数据,DMA的方法接收串口助手的数据,全部没问题,不过如果接收模块返回的数据,而这些数据如果包含回车换行的话就会停止接收,例如接收:AT\r\nOK\r\n,就只能接收到AT ...
- PC软件与PLC串口通信 奇偶检验问题
PC软件与PLC进行串口通信 波特率:19200 校验位:偶检验 数据位:8 停止位:1 现象 一,PC软件向PLC可以发送1,2,4,5,7,8,但是3,6,9发送出去后,PLC无法收到 二,使 ...
- 基于Verilog的带FIFO输出缓冲的串口接收接口封装
一.模块框图及基本思路 rx_module:串口接收的核心模块,详细介绍请见“基于Verilog的串口接收实验” rx2fifo_module:rx_module与rx_fifo之间的控制模块,其功能 ...
- 基于Verilog的串口接收程序
一.模块框图及基本思路 detect_module:检测输入引脚的下降沿,以此判断一帧数据的开始 rx_bps_module:波特率时钟产生模块 rx_control_module:串口接收的核心控制 ...
- STM32串口接收不定长数据原理与源程序(转)
今天说一下STM32单片机的接收不定长度字节数据的方法.由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的A ...
- stm32的串口接收字符串以十六进制数
#include "pbdata.h" uint8_t TxBuffer1[] = "USART Interrupt Example: This isUSART1 ...
- STM32 串口功能 库函数 详解和DMA 串口高级运用(转载)
数据传输时要从支持那些相关的标准?传输的速度?什么时候开始?什么时候结束?传输的内容?怎样防止通信出错?数据量大的时候怎么弄?硬件怎么连接出发,当然对于stm32还要熟悉库函数的功能 具起来rs232 ...
- 2018最新mfc作为上位机接收硬件端USB或串口数据显示成图片 解决串口接收数据丢字节丢包问题
原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/9490616.html 本文用的是VS2013MFC写串口数据接收: 第一步:首先建立一个MFC ...
随机推荐
- 移动 WEB 开发布局方式 ---- rem 适配布局
一.rem 基础 1. rem 单位 em : 相对于父元素的字体大小来说的 <div> <p></p> </div> div { font-size: ...
- R数据分析:孟德尔随机化中介的原理和实操
中介本身就是回归,基本上我看到的很多的调查性研究中在中介分析的方法部分都不会去提混杂,都是默认一个三角形画好,中介关系就算过去了,这里面默认的逻辑就是前两步回归中的混杂是一样的,计算中介效应的时候就自 ...
- SQL优化的七个方面
SQL优化的七个方面 1. 创建索引 禁止给表中每一列都建立单独索引 每个Innodb表都必须有一个主键 要注意组合索引的字段顺序 优先考虑覆盖索引 避免使用外键约束 2. 避免索引失效 失效场景: ...
- java数据库连接池笔记
(课程笔记来源于跟着老师敲,老师是黑马程序b站白嫖课程~) #数据库连接池: 1.概念:就是一个容器(集合),存放数据连接的容器 当容器初始化好后,容器会被创建,容器中会申请一些连接对象,当用户来 ...
- .NET Core 日志记录程序和常用日志记录框架
本文主要内容为.NET Core的日志记录程序和常使用的日志记录框架的简单使用 首先,打开VS2019新建一个ASP.NET Core Web Api项目,项目创建好后会有一个集成好的天气预报的类和控 ...
- steamdeck使用SSH远程控制
为了方便去折腾steamdeck,我想用Windows11远程控制steam deck,我开始在网上查找Linux远程控制的方法,决定使用SSH来达到目的. 首先开始查看我的steamdeck的ip地 ...
- EPICS Archiver Appliance在Debian11下安装文档
本文很想标注转发,可是要转发链接,只好标注原创. 首先声明:本文档是合肥光源控制组孙晓康博士踩坑后整理的.我尝试过在Debian11和Rocky下安装,碰到坎过不去,这段时间各种事就没继续了,请教晓康 ...
- A*算法小记
\(\text{A*}\) 一种启发式搜索 和暴搜的差别是多了一个估价函数,每次取出一个估算最优的状态以期更高效完成任务 重点在于估价函数 \(\text{h*(n)}\) 的设计,若实际代价为 \( ...
- 下载、编译AspNetCore 的全过程
1. clone 源码 下载新的 git clone --recursive https://github.com/dotnet/aspnetcore 如果之前clone过,但是没有使用 --recu ...
- vue弹窗后如何禁止滚动条滚动
toggleBody(isPin){ if(isPin){ document.body.style.height = '100vh' document.body.style['overflow-y'] ...