基于STM32的12864串行时序的实现
来源:互联网 发布:淘宝怎么提升信誉 编辑:程序博客网 时间:2024/05/17 07:55
12864液晶并口驱动程序用的比较多,但是考虑到有的时候单片机或者MCU的IO口有限时就可以使用串行驱动方法。以下是12864液晶串行时序图,下面就根据这个图来分析一下12864串行时序的实现,只有真正弄清楚了时序图才能真正了解串行传输的原理。
从图上可以看出串行传输时需要用到CS,SCLK,SID三根信号线,但是由于CS是高电平有效,所以也可以把CS长接高电平,那样就只需要两根线就OK了,当然当使用12864串行模式时,PSB引脚必须接低电平,复位RST引脚可以悬空不接,因为12864内部有上电复位电路。
void Write_8bits(uint W_bits){ uint i,Temp_data; for(i=0; i<8; i++)//总共移动八次,就可以把8bits数据全部传完 { Temp_data = W_bits; Temp_data <<= i;//把数据依次左移 if((Temp_data&0x80)==0) //判断对应位是否为0 { CLRSID;// SID = 0; CLRSCLK;//SCLK = 0;//在时钟的下降沿把数据传输出去 SETSCLK;// SCLK = 1;//置高电平,为下次传输做准备 } else //对应位为1 { SETSID;//SID = 1; CLRSCLK;//SCLK = 0; SETSCLK; //SCLK = 1; } }}
从时序图上可以看出,要想完整的把一个字节的数据传出去,需要传送三次才能实现,也就是需要传送三个字节,这三个字节分别是:命令控制字,字节的高四位+低四位0组成的字节,字节的低四位+高四位0组成的字节。
RW代表读还是写液晶,为0代表写,为1代表读。RS代表写命令还是数据,为0代表写命令,为1代表写数据,其余6位固定。所以假设要向液晶写数据,就必须首先发送11111010,写命令就发送11111000。
void W_1byte(uchar RW, uchar RS, uchar W_data){ uint H_data,L_data,S_ID = 0xf8; //11111RWRS0 if(RW == 0) { S_ID &=~ 0x04; } else //if(RW==1) { S_ID |= 0X04; } if(RS == 0) { S_ID &=~ 0x02; } else //if(RS==1) { S_ID |= 0X02; }//以上是根据读写命令以及是发送数据还是命令来组合命令字 H_data = W_data; H_data &= 0xf0; //屏蔽低4位的数据 L_data = W_data; //xxxx0000格式 L_data &= 0x0f; //屏蔽高4位的数据 L_data <<= 4; //xxxx0000格式 SETCS;//CS = 1; 时能发送 Write_8bits(S_ID); //发送命令字S_ID Write_8bits(H_data); //发送H_data Write_8bits(L_data); //发送L_data CLRCS;//CS=0 } //写入字符串 void LCD_write_string(uchar *s){ for(uint i=0;s[i]!='\0';i++) W_1byte(0,1,s[i]);} //液晶初始化函数 void LCD_Init_12864(void)//液晶初始化程序{ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); CLRPSB;//PSB=0 串行模式 OSTimeDly (40);//关于这个延时根据使用的单片机来决定我这里使用STM32 所以要加延时 W_1byte(0,0,0x30);//功能设置 8位数据,基本指令 OSTimeDly (40); W_1byte(0,0,0x02); //地址归位 OSTimeDly (40); W_1byte(0,0,0x06); //游标及显示右移一位 OSTimeDly (40); W_1byte(0,0,0x0c); //显示状态 ON,游标OFF,反白OFF OSTimeDly (40); W_1byte(0,0,0x01); //清除显示 OSTimeDly (40); W_1byte(0,0,0x81);//设置写入地址 LCD_write_string("STM32 ADC");} //附上一个实用的程序:把数字转换成字符串,n是转换的精度,即是字符串'.'后有几位小数//有的时候要把AD采样得到的浮点型转换成字符串在液晶上显示,这个函数就非常有用int ftoa(char *str, float num, int n) { int sumI; float sumF; int temp; int count = 0; char *p; char *pp; if(str == NULL) return -1; p = str; if(num < 0) { num = 0 - num; } sumI = (int)num; //sumI is the part of int sumF = num - sumI; //sumF is the part of float do { temp = sumI % 10; *(str++) = temp+48; }while((sumI = sumI /10) != 0); pp = str; pp--; while(p < pp) { *p = *p + *pp; *pp = *p - *pp; *p = *p -*pp; p++; pp--; } *(str++) = '.'; do { temp = (int)(sumF*10); *(str++) = temp+48; if((++count) == n) break; sumF = sumF*10 - temp; }while(!(sumF > -0.000001 && sumF < 0.000001)); *str='\0'; return 0;} //12864.h 12864头文件#include#define uchar CPU_INT08U#define uint CPU_INT16U#define SETCS GPIO_SetBits(GPIOC,GPIO_Pin_9) //CS PC.9#define SETSID GPIO_SetBits(GPIOC,GPIO_Pin_10) //SID PC.10#define SETSCLK GPIO_SetBits(GPIOC,GPIO_Pin_11) //SCLK PC.11#define SETPSB GPIO_SetBits(GPIOC,GPIO_Pin_12) //PSB PC.12#define CLRCS GPIO_ResetBits(GPIOC,GPIO_Pin_9)#define CLRSID GPIO_ResetBits(GPIOC,GPIO_Pin_10)#define CLRSCLK GPIO_ResetBits(GPIOC,GPIO_Pin_11)#define CLRPSB GPIO_ResetBits(GPIOC,GPIO_Pin_12)void W_1byte(uchar RW, uchar RS, uchar W_data);void LCD_Init_12864(void);int ftoa(char *str, float num, int n);void LCD_write_string(u8 *s);//主函数 实现功能STM32 ADC采样 在液晶上显示#include "12864.h"#define ADC1_DR_Address ((uint32_t)0x4001244C) //ADC数据寄存器的基地址USART_InitTypeDef USART_InitStructure; //串口、ADC、DMA声明ADC_InitTypeDef ADC_InitStructure;DMA_InitTypeDef DMA_InitStructure; // 注:ADC为12位模数转换器,只有ADCConvertedValue的低12位有效 uint16_t ADCConvertedValue;void ADC_GPIO_Configuration(void);static void Delay_ARMJISHU(__IO uint32_t nCount){ for (; nCount != 0; nCount--);}uchar tab1[]="0123456789";int main(void){ GPIO_InitTypeDef GPIO_InitStructure; u16 ADCConvertedValueLocal, Precent = 0, Voltage = 0; ADC_GPIO_Configuration(); //Delay_ARMJISHU(1000000);//延时 上电复位 不然需要手动复位 LCD_Init_12864();//液晶初始化程序 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA时钟 DMA_DeInit(DMA1_Channel1); //开启DMA1的第一通道 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //DMA对应的外设基地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue; //内存存储基地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //DMA的转换模式为SRC模式,由外设搬移到内存 DMA_InitStructure.DMA_BufferSize = 1;//DMA缓存大小,1个 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //接收一次数据后,设备地址禁止后移 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //关闭接收一次数据后,目标内存地址后移 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //定义外设数据宽度为16位 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //DMA搬移数据尺寸,HalfWord就是为16位 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //转换模式,循环缓存模式。 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级高 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //M2M模式禁用 DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_GPIO_Configuration(); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立的转换模式 ADC_DUALMOD[3:0]=0000; ADC_InitStructure.ADC_ScanConvMode = ENABLE;//开启扫描模式 ADC_SCAN=1; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换模式 ADC_CONT=1; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC外部开关,关闭状态 ; 软件转换 ADC_EXTSEL[2:0]=111; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//对齐方式,ADC为12位中,右对齐方式 ADC_ALIGN=0; ADC_InitStructure.ADC_NbrOfChannel = 1;//开启通道数,1个 ADC_SQR1[23:20]=0000; //ADC_SQR1[23:20] 设置通道数目的选择 ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_9, 1, ADC_SampleTime_55Cycles5); //ADC_SMPR2 ADC_SMPR1 设置每个通道的采样时间 //ADC_SQR1[19:0]DC_SQR1[29:0]DC_SQR3[29:0] 设置对应通道的转换顺序 适用于多通道采样 //ADC通道组, 第9个通道 采样顺序1,转换时间 ADC_DMACmd(ADC1, ENABLE); //ADC命令,使能 ADC_ADON=1 ADC_Cmd(ADC1, ENABLE); //开启ADC1 ADC_DMA=1 ADC_ResetCalibration(ADC1); //重新校准 while(ADC_GetResetCalibrationStatus(ADC1)); //等待重新校准完成 ADC_StartCalibration(ADC1); //开始校准 ADC_RSTCAL=1; 初始化校准寄存器 while(ADC_GetCalibrationStatus(ADC1)); //等待校准完成 ADC_CAL=0; ADC_SoftwareStartConvCmd(ADC1, ENABLE); //连续转换开始,ADC通过DMA方式不断的更新RAM区。//ADC_SWSTART=1 开始规则转换 切记 软件触发也属于外部事件 要设置 ADC_EXTTRIG=1 while (1) { ADCConvertedValueLocal = ADCConvertedValue; Precent = (ADCConvertedValueLocal*100/0x1000);//算出百分比 Voltage = Precent*33; //3.3V的电平,计算等效电平 W_1byte(0,0,0x91); W_1byte(0,1,tab1[Precent/10]); W_1byte(0,1,tab1[Precent]); W_1byte(0,1,'%'); W_1byte(0,1,' '); W_1byte(0,1,tab1[Voltage/1000]); W_1byte(0,1,'.'); W_1byte(0,1,tab1[(Voltage00)/100]); W_1byte(0,1,tab1[(Voltage0)/10]); W_1byte(0,1,'V'); }}void ADC_GPIO_Configuration(void) //ADC配置函数{ GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA, ENABLE); //使能ADC和GPIOC时钟 //PB1 作为模拟通道输入引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; //管脚1 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //输入模式 GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIO组}
1 0
- 基于STM32的12864串行时序的实现
- 串行通讯的时序分析
- STM32 入门教程 基于 MDK 的 SWD 两线串行仿真
- 串行AD芯片ADC12S021的时序问题
- STM32驱动ST7920的12864液晶(串行方式)
- 基于FPGA的RS232串行接口的实现
- ambe1000在stm32下的串行驱动
- 基于STM32的简单电子书的实现
- STM32访问外部存储器的时序计算
- 串行通信的实现
- K60学习笔记五:串行通信的时序分析
- 基于事件的时序控制
- 基于VC的串行通信技术应用
- 基于VC的串行通信技术应用
- WINCE基于AT050TN22屏的时序描述
- 基于AWS的时序处理应用架构
- 基于时序数据库的GPS处理方案
- stm32基于Can和uart的IAP实现
- 股票学习(财务分析13)
- 通过java对数据库的增删查修操作
- 算法导论 第三十三章:字符串匹配
- [刘未鹏]怎样花两年时间去面试一个人
- 数据结构(二):线性表包括顺序存储结构(顺序表、顺序队列和顺序栈)和链式存储结构(链表、链队列和链栈)
- 基于STM32的12864串行时序的实现
- 代码签名探析
- device contexts
- C语言冒泡序列把数字从大到小排列
- 首字母变大写 --输入一个英文句子,将每个单词的第一个字母改成大写字母。
- android ndk开发hello world入门
- python 第三方 .whl包安装及出现的IOError问题解决办法
- linux中的lsof命令简介
- 2015072105 - 17个来回