STM32 0.96 与 0.91 OLED 的屏幕使用
双重 ADC 同步规则模式采集实验与多路LCD 波形示波器制作显示,本文展示了STM32 AD 双重 ADC 同步规则模式采集实验。
STM32 AD 采集往期回顾
1 STM32F103 AD多通道DMA采集 独立模式与多路LCD 波形示波器制作显示 以及蓝牙传输串口数据
2 STM32F103 AD独立模式单通道采集 与LCD触摸 波形显示
代码:
内容涉及 :
- STM32 AD 双重 ADC 同步规则
- AD多通道DMA采集与存储调用
- AD采样点的构造体封装
- AD 的处理以及 LCD波形输出 模仿示波器的原理
- LCD触摸画板的控制
- SRAM 内存扩展管理
- FatFs 文件系统移植
- SPI函数移植过程
- SPI字节数据模拟输出独写 缓存读写
- USART串口的识别
- IO口输入输出
- 按键的外部中断处理
- 32位数据通讯,字符串通讯,单字符通讯
一:编程要点
- 初始 ADC 用到的 GPIO;
- 初始化 ADC GPIO;
- 初始化 DMA 配置;
- 初始化 ADC 参数;
- 读取 ADC
- 采集的数据,并打印出来校正;
- 设置 ADC 的工作参数并初始化;
- 设置 ADC 工作时钟;
- 设置 ADC 转换通道顺序及采样时间;
- 配置DMA 工作参数;
- 使能 ADC 7) 读取 ADC 采集的数据。
同步规则模式是 ADC1 和 ADC2 同时转换一个规则通道组,ADC1 是主,ADC2 是从。
ADC1 转换的结果放在 ADC1_DR 的低 16位,ADC2 转换的结果放在 ADC1_DR 的高十六位。
并且必须开启 DMA 功能。外部触发来自 ADC1 的规则组多路开关(由 ADC1_CR2 寄存器的 EXTSEL[2:0]选择)。
它同时给 ADC2 提供同步触发。为了简单起见,ADC1 我们选择软件触发,ADC2 必须选择外部触发。
这个外部触发来自于 ADC1 的规则组多路开关。
二:ADC 的工作具体如下
<font color=#FF00000>
AD转换包括采样阶段和转换阶段,在采样阶段才对通道数据进行采集;
而在转换阶段只是将采集到的数据进行转换为数字量输出,此刻通道数据变化不会改变转换结果。
独立模式的 ADC 采集需要在一个通道采集并且转换完成后才会进行下一个通道的采集。
而双重 ADC 的机制就是使用两个 ADC 同时采样一个或者多个通道。
双重 ADC 模式较独立模式一个最大的优势就是提高了采样率,弥补了单个 ADC 采样不够快的缺点。
启用双 ADC模式的时候,通过配置 ADC_CR1寄存器的 DUALMOD[3:0]位,可以有几种不同的模式,具体见表格 31-1
三:代码分析
1:ADC_book.h
代码如下:
#ifndef __ADC_BOOK_H
#define __ADC_BOOK_H
#include "stm32f10x.h"
// ADC GPIO宏定义
// 注意:用作ADC采集的IO必须没有复用,否则采集电压会有影响// ADC 编号选择
// 可以是 ADC1/2,如果使用ADC3,中断相关的要改成ADC3的
#define ADC_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADC_GPIO_CLK RCC_APB2Periph_GPIOC
#define ADC_PORT GPIOC
// ADC 编号选择
// 可以是 ADC1/2,如果使用ADC3,中断相关的要改成ADC3的
#define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADC_X ADC1 //ADC2
#define ADC_Y ADC2 //ADC2
#define ADC_CLKX RCC_APB2Periph_ADC1
#define ADC_CLKY RCC_APB2Periph_ADC2
//-------------------------------- ADC DMA 配置 ------------------------
// ADC1 对应 DMA1 通道 1,ADC3 对应 DMA2 通道 5,ADC2 没有 DMA 功能
#define ADC_DMA_CLK RCC_AHBPeriph_DMA1
#define ADC_DMA_CHANEL DMA1_Channel1
#endif
//ADC 中断相关宏定义
#define ADC_IRQ ADC1_2_IRQn
#define ADC_IRQHandler ADC1_2_IRQHandler
//-------------------------------- ADC配置 ------------------------------
// 双通道ADC同步设计
#define __ADC_RegSimult_Mode__ //使能标志位
#ifdef __ADC_RegSimult_Mode__
#define NOFCHANEL 2 //转换通道的个数
#define _DMA_BufferSize 1
#define ADC_PIN1 GPIO_Pin_1
#define ADC_CHANNEL1 ADC_Channel_11
#define ADC_PIN4 GPIO_Pin_4
#define ADC_CHANNEL4 ADC_Channel_14
#endif
typedef union {
struct{
unsigned char BIT0:1;unsigned char BIT1:1;unsigned char BIT2:1;unsigned char BIT3:1;
unsigned char BIT4:1;unsigned char BIT5:1;unsigned char BIT6:1;unsigned char BIT7:1;
//unsigned char BIT8:1;unsigned char BIT9:1;unsigned char BIT10:1;unsigned char BIT11:1;
//unsigned char BIT12:1;unsigned char BIT13:1;unsigned char BIT14:1;unsigned char BIT15:1;
}DATA_BIT;
uint8_t DATA_BYTE;
}Per_adc_type;
extern volatile Per_adc_type adc_flag;
#define badc_10ms adc_flag.DATA_BIT.BIT0
extern volatile uint32_t Count_Adc_flag;
//----------- 双通道ADC同步设计-------
#ifdef __ADC_RegSimult_Mode__
extern volatile uint32_t ADC_RegSimult_ConvertedValue[NOFCHANEL];
extern volatile float ADC_RegSimult_ConvertedValueLocal[NOFCHANEL];
#endif
void ADCx_Init(void);
void ADC_get_value(void);
#endif
2:ADC_book.c
使用到 GPIO 时候都必须开启对应的 GPIO 时钟,GPIO 用于 AD 转换功能必须配置为模拟输入模式。
ADCx_Mode_Config()与独立模式多通道配置基本一样,只是有几点需要注意:
ADC 工作模式要设置为同步规则模式;两个 ADC 的通道的采样时间需要一致;
ADC1设置为软件触发;ADC2 设置为外部触发。其他的基本一样,看代码注释理解即可。
#include "ADC_book.h"
#include "XPT2046_LCD_GridDiagram_book.h"
volatile Per_adc_type adc_flag;
volatile uint32_t Count_Adc_flag;
#ifdef __ADC_RegSimult_Mode__
__IO uint32_t ADC_RegSimult_ConvertedValue[NOFCHANEL]={0,0};
__IO uint32_t ADC_RegSimult_ConvertedValue_Show[NOFCHANEL]={0,0};
__IO float ADC_RegSimult_ConvertedValueLocal[NOFCHANEL];
#endif
/**
* @brief ADC GPIO 初始化函数
* @param 无
* @retval 无
*/
static void ADCx_GPIO_Config(void){
GPIO_InitTypeDef GPIO_InitStructure;
// 打开ADC IO 端口时钟
ADC_GPIO_APBxClock_FUN (ADC_GPIO_CLK , ENABLE);
//配置 ADC IO 端口的模式
//-----------双通道ADC同步设计-------------
#ifdef __ADC_RegSimult_Mode__
GPIO_InitStructure.GPIO_Pin = ADC_PIN1|
ADC_PIN4;
#endif
// 必须为模拟输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
//初始化 ADDC_IO
GPIO_Init(ADC_PORT , &GPIO_InitStructure );
}
/**
* @brief 配置ADC DMA 工作模式
* @param
* @retval
*/
static void ADCx_DMA_Config(void){
DMA_InitTypeDef DMA_InitStructure;
//打开DMA时钟
RCC_AHBPeriphClockCmd(ADC_DMA_CLK , ENABLE);
//复位DMA 控制器
DMA_DeInit(ADC_DMA_CHANEL);
//配置DMA初始化结构体
// 外设基址为:ADC 数据寄存器地址
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(ADC_X->DR));
// 存储器地址,实际上就是一个内部SRAM的变量
#ifdef __ADC_RegSimult_Mode__
//----------- 双通道ADC同步设计-------
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_RegSimult_ConvertedValue;
#endif
// 数据源来自外设
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
// 缓冲区大小为1,缓冲区的大小应该等于存储器的大小
DMA_InitStructure.DMA_BufferSize = _DMA_BufferSize ;
// 外设寄存器只有一个,地址不用递增
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
#ifdef __ADC_RegSimult_Mode__
// 外设数据大小为半字,即两个字节
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
// 存储器数据大小也为半字,跟外设数据大小相同
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
#else
// 外设数据大小为半字,即两个字节
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
// 存储器数据大小也为半字,跟外设数据大小相同
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
#endif
// 循环传输模式
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
// DMA 传输通道优先级为高,当使用一个DMA通道时,优先级设置不影响
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
// 禁止存储器到存储器模式,因为是从外设到存储器
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
// 初始化DMA
DMA_Init(ADC_DMA_CHANEL,&DMA_InitStructure);
// 使能 DMA 通道
DMA_Cmd(ADC_DMA_CHANEL , ENABLE);
}
/**
* @brief 配置ADC 工作模式
* @param
* @retval
*/
static void ADCx_Mode_Config(void){
ADC_InitTypeDef ADC_InitStructure;
//----------- 双通道ADC同步设计-------
#ifdef __ADC_RegSimult_Mode__
//打开ADC时钟
ADC_APBxClock_FUN (ADC_CLKX , ENABLE);
ADC_APBxClock_FUN (ADC_CLKY , ENABLE);
#else
ADC_APBxClock_FUN (ADC_CLKX , ENABLE);
#endif
//--------ADC 模式配置 -----
//----------- 双通道ADC同步设计-------
#ifdef __ADC_RegSimult_Mode__
// 双 ADC 的规则同步
ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
// 扫描模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
#endif
//连续转换模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
// 不用外部触发转换 ,软件开启即可
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
//转换结果右侧对齐
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
//----------- 双通道ADC同步设计-------
#ifdef __ADC_RegSimult_Mode__
ADC_InitStructure.ADC_NbrOfChannel = NOFCHANEL/2;
//初始化ADC
ADC_Init(ADC_X , &ADC_InitStructure);
ADC_Init(ADC_Y , &ADC_InitStructure);
#endif
//配置ADC时钟为PCLCK2的8分频 为9HZ
RCC_ADCCLKConfig(RCC_PCLK2_Div8);
//配置ADC转换通道转换顺序和采样时间
//----------- 双通道ADC同步设计-------
#ifdef __ADC_RegSimult_Mode__
ADC_RegularChannelConfig(ADC_X , ADC_CHANNEL1 , 1 , ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC_Y , ADC_CHANNEL4 , 1 , ADC_SampleTime_239Cycles5);
#endif
//-----------AD通道采集-------
//-----------DMA模式----------
#ifdef __ADC_DMA_Mode__
#ifdef __ADC_RegSimult_Mode__
// 只需要使能ADC1 DMA 请求
//ADC1 我们选择软件触发,ADC2 必须选
//择外部触发,这个外部触发来自于 ADC1 的规则组多路开关。
ADC_DMACmd(ADC_X, ENABLE);
/* 使能 ADCx_2 的外部触发转换 */
ADC_ExternalTrigConvCmd(ADC_Y, ENABLE);
#else
// 使能ADC DMA 请求
ADC_DMACmd(ADC_X, ENABLE);
#endif
#else
//ADC 转换结束产生中断,在中断服务程序中读取转换值
ADC_ITConfig(ADC_X , ADC_IT_EOC , ENABLE);
// 使能ADC DMA 请求
ADC_DMACmd(ADC_X, ENABLE);
#endif
//-----------DMA模式----------
/* ----------------ADC 校准--------------------- */
//----------- 双通道ADC同步设计-------
#ifdef __ADC_RegSimult_Mode__
//开启ADC 并开始转换
ADC_Cmd(ADC_X , ENABLE);
// 初始化ADC 校准寄存器
ADC_ResetCalibration(ADC_X);
// 等待校准寄存器初始化完成
while(ADC_GetResetCalibrationStatus(ADC_X));
//ADC_采集校准
ADC_StartCalibration(ADC_X);
//等待校准完成
while(ADC_GetCalibrationStatus(ADC_X));
//开启ADC 并开始转换
ADC_Cmd(ADC_Y , ENABLE);
// 初始化ADC 校准寄存器
ADC_ResetCalibration(ADC_Y);
// 等待校准寄存器初始化完成
while(ADC_GetResetCalibrationStatus(ADC_Y));
//ADC_采集校准
ADC_StartCalibration(ADC_Y);
//等待校准完成
while(ADC_GetCalibrationStatus(ADC_Y));
//由于没有采用外部触发 ,所以使用软件ADC转换
//ADC 工作模式要设置为同步规则模式;两个 ADC 的通道的采样时间需要一致;
//ADC1设置为软件触发;ADC2 设置为外部触发
ADC_SoftwareStartConvCmd(ADC_X , ENABLE);
}
static void ADC_NVIC_Config(void){
NVIC_InitTypeDef NVIC_InitStructure;
//优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
//配置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void ADC_IRQHandler(void){
if( ADC_GetITStatus(ADC_X , ADC_IT_EOC )==SET ){
//读取ADC的转换值
//--------DMA模式-----
#ifdef __ADC_DMA_Mode__
#else
ADC_ConvertedValue = ADC_GetConversionValue(ADC_X);
#endif
//--------DMA模式-----
ADC_ClearITPendingBit(ADC_X , ADC_IT_EOC);
}
if( ADC_GetITStatus(ADC_Y , ADC_IT_EOC )==SET ){
//读取ADC的转换值
//--------DMA模式-----
#ifdef __ADC_DMA_Mode__
#else
ADC_ConvertedValue = ADC_GetConversionValue(ADC_Y);
#endif
//--------DMA模式-----
ADC_ClearITPendingBit(ADC_Y , ADC_IT_EOC);
}
}
/**********************END OF FILE**********************/
/**
* @brief ADC初始化
* @param 无
* @retval 无
*/
void ADCx_Init(void){
//--------DMA模式-----
#ifdef __ADC_DMA_Mode__
ADCx_GPIO_Config();
ADCx_DMA_Config();
ADCx_Mode_Config();
#else
ADCx_GPIO_Config();
ADCx_Mode_Config();
ADC_NVIC_Config(); // DMA 模式不需要对中断进行处理
#endif
//--------DMA模式-----
}
void ADC_get_value(void){
uint16_t temp0=0 ,temp1=0;
if(badc_10ms==0){return;}
badc_10ms = 0;
//-----------AD通道采集-------
#ifdef __ADC_RegSimult_Mode__
// 取出 ADC1 数据寄存器的高 16 位,这个是 ADC2 的转换数据
temp0 = (ADC_RegSimult_ConvertedValue[0]&0XFFFF0000) >> 16;
// 取出 ADC1 数据寄存器的低 16 位,这个是 ADC1 的转换数据
temp1 = (ADC_RegSimult_ConvertedValue[0]&0XFFFF);
printf("The current AD value %d = 0x%08X \r\n",0,ADC_RegSimult_ConvertedValue[0]);
ADC_RegSimult_ConvertedValue_Show[0] = temp0 ;
ADC_RegSimult_ConvertedValue_Show[1] = temp1 ;
ADC_RegSimult_ConvertedValueLocal[0] = (float)temp0 /4096*3.3;
ADC_RegSimult_ConvertedValueLocal[1] = (float)temp1 /4096*3.3;
printf("The current AD value %d = 0x%04X %f V\r\n",0,ADC_RegSimult_ConvertedValue_Show[0],ADC_RegSimult_ConvertedValueLocal[0]);
printf("The current AD value %d = 0x%04X %f V\r\n",1,ADC_RegSimult_ConvertedValue_Show[1],ADC_RegSimult_ConvertedValueLocal[1]);
printf("\r\n\r\n");
GDScream_Data_show( ADC_RegSimult_ConvertedValue_Show,NOFCHANEL);
#endif
}
3:main.c
代码如下:
/*******************************************************************************
* @file GPIO/JTAG_Remap/main.c
* @author MCD Application Team
* @version V3.5.0
* @date 08-April-2011
* @brief Main program body
******************************************************************************
* @attention
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "PROJ_book.h"
/**
* @brief Main program.
* @param None
* @retval None
*/
void delay(int x);
void fn_LED_Flash_Init(void);
void fn_usart_show_Init(void);
void fn_DMA_show_Init(void);
void fn_I2C_EE_Init(void);
void fn_I2C_EE_Soft_Init(void);
void fn_SPI_FLASH_Soft_Init(void);
void fn_FatFs_Document_Init(void);
void fn_SRAM_Init(void);
void fn_LCD_Init(void);
void fn_XPT2046_Init(void);
void fn_Adc_Init(void);
#define countof(a) (sizeof(a) / sizeof(*(a)))
#define _I2C_BufferSize (countof(writeData)-1)
static uint8_t writeData[_I2C_PageSize]={4,5,6,7,8,9,10,11};
static uint8_t writeData2[_I2C_PageSize]={24,25,26,27,28,29,30,31};
static uint8_t ReadData[_I2C_BufferSize]={0};
#define _SPI_BufferSize SPI_PAGE_SIZE //(countof(write_SPI_Data)-1)
static uint8_t write_SPI_Data[_SPI_BufferSize]={0};
static uint8_t Read_SPI_Data[_SPI_BufferSize]={0};
int main(void)
{
int16_t sAD_X, sAD_Y ;
fn_Adc_Init(); //ADC 采集
//*************LCD系统初始化**************
fn_XPT2046_Init();
fn_Lcd_Page_Init();
fn_Lcd_Page4();
while(1){
ADC_get_value();
}
}
//======================================================================
//======================================================================
void fn_LCD_Init(void){ //LCD运行测试
__IO int16_t int_check;
fn_Systick_Delay(500,_Systick_ms);
int_check = (__IO int16_t)ILI9341_Init();
Display_LCD_clear();
switch(int_check){
case 0x05:
printf("\n-->LCD 运行正常\r\n");
Lcd_display_String(" LCD 运行正常\r\n");
break;
default:
printf("\n-->LCD 运行异常\r\n");
Lcd_display_String(" LCD 运行异常\r\n\r\n");
}
}
//======================================================================
//======================================================================
void fn_XPT2046_Init(void){ //XPT2046运行测试
printf("\n-->LCD 触摸初始化\r\n");
Lcd_display_String(" LCD 触摸初始化\r\n");
XPT2046_GPIO_Init();
// while(XPT2046_Touch_Calibrate_Page() == 0){;}
Lcd_display_String(" LCD 触摸初始化ok\r\n");
}
//======================================================================
//======================================================================
void fn_Adc_Init(void){
ADCx_Init();
}
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
4: XPT2046_LCD_GridDiagram_book.h
代码如下:
#ifndef __XPT2046_LCD_GRIDDIAGRAM_BOOK__
#define __XPT2046_LCD_GRIDDIAGRAM_BOOK__
#include "stm32f10x.h"
#include "XPT2046_LCD_Function_book.h"
#include "XPT2046_LCD_book.h"
#include "LCD_book.h"
#include "LCD_Draw_book.h"
#include "XPT2046_LCD_Device_book.h"
#include "ADC_book.h"
#include "USART_book.h"
//======================================================形式是默认还是定制化=====================================================
/**
模式0: . 模式1: . 模式2: . 模式3:
A . A . A . A
| . | . | . |
Y . X . Y . X
0 . 1 . 2 . 3
<--- X0 o . <----Y1 o . o 2X---> . o 3Y--->
------------------------------------------------------------
模式4: . 模式5: . 模式6: . 模式7:
<--- X4 o . <--- Y5 o . o 6X---> . o 7Y--->
4 . 5 . 6 . 7
Y . X . Y . X
| . | . | . |
V . V . V . V
---------------------------------------------------------
LCD屏示例
|---------|-----------------------------|
| AD测试 | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
|---------|-----------------------------|
屏幕正面(宽240,高320)270 50 -2
**/
///******************************* XPT2046 触摸屏参数定义 ***************************/
#define XPT2046_GDCHANNEL_X ILI9341_MORE_PIXEL //通道Y+的选择控制字
#define XPT2046_GDCHANNEL_Y ILI9341_LESS_PIXEL //通道X+的选择控制字
#define LCD_GDWork_X_LENGTH 270
#define LCD_GDNwork_Y_LENGTH 238
#define LCD_GDControl_X_Start 0
#define LCD_GDControl_Y_Start 0
#define LCD_GDControl_X_LENGTH (XPT2046_GDCHANNEL_X - LCD_GDWork_X_LENGTH - 2)
#define LCD_GDControl_Y_LENGTH XPT2046_GDCHANNEL_Y
#define LCD_GDSCAN_X_Start (LCD_GDControl_X_LENGTH+1)
#define LCD_GDSCAN_Y_Start 1
#define LCD_GDSCAN_X_LENGTH LCD_GDWork_X_LENGTH
#define LCD_GDSCAN_Y_LENGTH LCD_GDNwork_Y_LENGTH
#define LCD_GDSCAN_X_End (XPT2046_GDCHANNEL_X-1)
#define LCD_GDSCAN_Y_End (XPT2046_GDCHANNEL_Y-1)
#define Center_lineNum 6
#define GDBUTTON_NUM 3
typedef struct{
int16_t value_x_before ;
int16_t value_x_now ;
int16_t value_y_before ;
int16_t value_y_now ;
uint32_t para_color;
uint16_t data_value;
void (*draw_point)(void *draw_pot); //按键描绘函数
}AD_Point;
void GDScream_Data_show(int32_t *data_value , uint16_t data_num);
#endif
5: XPT2046_LCD_GridDiagram_book.c
代码如下:
/**
******************************************************************************
* @file palette.c
* @author fire
* @version V1.0
* @date
* @brief 触摸画板应用函数
******************************************************************************
* @attention
*
******************************************************************************
*/
#include "XPT2046_LCD_GridDiagram_book.h"
#include <stdio.h>
#include <string.h>
Touch_Button GDbutton[GDBUTTON_NUM];
static void GDTouch_Button_Init(void);
static void Draw_btn_GDcontrol_Button(void *btn);
static void Btn_command_GDcontrol_Button(void);
static void GDControl_Text_Init(void);
static void GDScream_show_Init(void);
static void GDScream_Line_Init(void);
static void GDScream_Data_show_init(void);
static void Draw_point(void * draw_pot);
/**
* @brief Palette_Init 画板初始化
* @param 无
* @retval 无
*/
#define _LCD_GDSCAN_MODE LCD_SCAN_MODE_3
void GridDiagram_Init(void){
uint16_t datax , datay;
ILI9341_GramScan(_LCD_GDSCAN_MODE);
//初始化画板颜色
LCD_SetBackColor(CL_GREY2);
ILI9341_Clear(0,0,XPT2046_GDCHANNEL_X+1,XPT2046_GDCHANNEL_Y+1);
LCD_SetColors(CL_YELLOW , CL_WHITE);
ILI9341_DrawRectangle(1,1,LCD_GDControl_X_LENGTH-1,LCD_GDControl_Y_LENGTH-1,0,1);
LCD_SetColors(CL_WHITE , CL_WHITE);
ILI9341_DrawRectangle(LCD_GDControl_X_Start ,
LCD_GDControl_Y_Start ,
LCD_GDControl_X_LENGTH,
LCD_GDControl_Y_LENGTH,0,1);
LCD_SetColors(CL_BLACK , CL_WHITE);
ILI9341_DrawRectangle(LCD_GDSCAN_X_Start,
LCD_GDSCAN_Y_Start,
LCD_GDSCAN_X_LENGTH,
LCD_GDSCAN_Y_LENGTH,1,1);
GDScream_Line_Init();
GDScream_Data_show_init();
//初始化按钮
GDTouch_Button_Init();
GDControl_Text_Init();
//对属性物件进行刷新
GDScream_show_Init();
}
/**
* @brief GDTouch_Button_Init 画板初始化
* @param 无
* @retval 无
*/
static void GDTouch_Button_Init(void){
uint8_t i ;
for(i = 0 ;i<=GDBUTTON_NUM ;i++ ){
GDbutton[i].start_x = BUTTON_START_X+3;
GDbutton[i].end_x = GDbutton[i].start_x+COLOR_BLOCK_WIDTH ;
GDbutton[i].start_y = (COLOR_BLOCK_HEIGHT + 20)*(i+1);
GDbutton[i].end_y = GDbutton[i].start_y + COLOR_BLOCK_HEIGHT ;
GDbutton[i].touch_flag = 0;
GDbutton[i].draw_btn = Draw_btn_GDcontrol_Button ;
GDbutton[i].btn_command = Btn_command_GDcontrol_Button ;
}
GDbutton[0].para = CL_GREY; //构建按钮的属性
GDbutton[1].para = CL_GREY; //构建按钮的属性
GDbutton[2].para = CL_GREY; //构建按钮的属性
//描绘按钮
for(i=0 ;i<GDBUTTON_NUM ;i++ ){
GDbutton[i].draw_btn(&GDbutton[i]);
}
}
/**
* @brief Draw_btn_GDcontrol_Button 画板初始化
* @param 无
* @retval 无
*/
static void Draw_btn_GDcontrol_Button(void *btn){
Touch_Button *ptr = (Touch_Button *)btn;
//释放按键
if( ptr->touch_flag == 0){
//背景为功能键的颜色
LCD_SetColors(ptr->para , CL_WHITE);
ILI9341_DrawRectangle(ptr->start_x , ptr->start_y,\
ptr->end_x - ptr->start_x,\
ptr->end_y - ptr->start_y,1,1);
//白色背景边框
LCD_SetColors(CL_BOX_BORDER1 , CL_WHITE);
ILI9341_DrawRectangle(ptr->start_x , ptr->start_y,\
ptr->end_x - ptr->start_x,\
ptr->end_y - ptr->start_y,0,2);
}else{//按键按下
//白色背景
LCD_SetColors(CL_WHITE , CL_WHITE);
ILI9341_DrawRectangle(ptr->start_x , ptr->start_y,\
ptr->end_x - ptr->start_x,\
ptr->end_y - ptr->start_y,1,1);
//白色背景边框
LCD_SetColors(CL_BOX_BORDER2 , CL_WHITE);
ILI9341_DrawRectangle(ptr->start_x , ptr->start_y,\
ptr->end_x - ptr->start_x,\
ptr->end_y - ptr->start_y,0,2);
}
}
/**
* @brief Btn_command_GDcontrol_Button 画板初始化
* @param 无
* @retval 无
*/
static void Btn_command_GDcontrol_Button(void){
;
}
/**
* @brief Draw_btn_GDcontrol_Button 画板初始化
* @param 无
* @retval 无
*/
static void GDControl_Text_Init(void){
LCD_SetColors(CL_RED,CL_WHITE);
/*选择字体,使用中英文显示时,尽量把英文选择成8*16的字体,
*中文字体大小是16*16的,需要其它字体请自行制作字模*/
/*这个函数只对英文字体起作用*/
LCD_SetFont(&Font8x16);
ILI9341_DispString_EN_CH( LCD_GDControl_X_Start +2, LCD_GDControl_Y_Start + 5, "AD检查");
LCD_SetColors(CL_BLACK,CL_WHITE);
/*选择字体,使用中英文显示时,尽量把英文选择成8*16的字体,
*中文字体大小是16*16的,需要其它字体请自行制作字模*/
/*这个函数只对英文字体起作用*/
LCD_SetFont(&Font8x16);
ILI9341_DispString_EN_CH( LCD_GDControl_X_Start +2, LCD_GDControl_Y_Start + 25, " 王琪");
}
/**
* @brief Draw_btn_GDcontrol_Button 画板初始化
* @param 无
* @retval 无
*/
static void GDScream_Line_Init(void){
uint8_t i ;
uint16_t center_linexstart , center_lineystart ,center_linexend , center_lineyend;
uint16_t center_linespace ;
center_linexstart = LCD_GDSCAN_X_Start ;
center_lineystart = XPT2046_GDCHANNEL_Y / 2;
center_linexend = LCD_GDSCAN_X_End;
center_lineyend = center_lineystart ;
center_linespace = (XPT2046_GDCHANNEL_Y - 2 )/Center_lineNum ;
LCD_SetColors(CL_RED , CL_WHITE);
ILI9341_DrawLine( center_linexstart ,center_lineystart ,center_linexend ,center_lineyend,1 );
LCD_SetColors(CL_YELLOW , CL_WHITE);
ILI9341_DrawLine( center_linexstart ,center_lineystart + center_linespace ,center_linexend ,center_lineyend + center_linespace,1 );
ILI9341_DrawLine( center_linexstart ,center_lineystart - center_linespace ,center_linexend ,center_lineyend - center_linespace,1 );
LCD_SetColors(CL_BLUE , CL_WHITE);
ILI9341_DrawLine( center_linexstart ,center_lineystart + (center_linespace*2) ,center_linexend ,center_lineystart + (center_linespace*2),1 );
ILI9341_DrawLine( center_linexstart ,center_lineystart - (center_linespace*2) ,center_linexend ,center_lineystart - (center_linespace*2),1 );
}
/**
* @brief Draw_btn_GDcontrol_Button 画板初始化
* @param 无
* @retval 无
*/
static void GDScream_show_Init(void){
uint8_t i ;
for( i=0 ; i< (GDBUTTON_NUM); i++ ) {
GDbutton[i].draw_btn(&GDbutton[i]);
}
}
//===============================================关于屏幕画点的程序函数==============================================
// 屏幕正面(宽320,高240)
// 270 个像素
// 238 / 6 38
// 500MS 一个数字
// 像素间隔 Dx = 2 = 135 个数字
// 可以测试85S 的数据
// 4096 12 AD 每个像素高度为 20 *38 = 760 大约 0.6V 精度为0.02V
// 设定变量 :uint16 data_value / DX = 2 DY = 1 HX= 1 HY = 20 , uint16 data_value_before data_value_now ,
#define DX 1
#define DY 1
#define HX 1
#define HY 20
__IO int16_t data_value_x_before = -1; //之前的状态点
__IO int16_t data_value_x_now = -1; // 现在的状态点
__IO int16_t data_value_y_before = -1;
__IO int16_t data_value_y_now = -1;
AD_Point ad_point[NOFCHANEL]; //采样数据模块
static void GDScream_Data_show_init(void){ //显示数据AD的样式初始化
uint8_t i=0 ;
data_value_x_before = -1 ;
data_value_x_now = -1;
data_value_y_before = -1 ;
data_value_y_now = -1;
for( i=0;i<NOFCHANEL ;i++ ){
ad_point[i].value_x_before =data_value_x_before;
ad_point[i].value_x_now = data_value_x_now;
ad_point[i].value_y_before = data_value_y_before ;
ad_point[i].value_y_now = data_value_y_now;
ad_point[i].draw_point = Draw_point;
}
ad_point[0].para_color = CL_WHITE;
ad_point[1].para_color = CL_GREEN;
ad_point[2].para_color = CL_GREY3;
ad_point[3].para_color = CL_YELLOW;
ad_point[4].para_color = CL_BLUE;
ad_point[5].para_color = CL_MAGENTA;
}
static void Draw_point(void *draw_pot){ //AD模块采样点的绘制功能
AD_Point *ptr_point = (AD_Point *)draw_pot;
if((ptr_point->value_x_before) == -1){
ILI9341_SetPointPixel(ptr_point->value_x_now,ptr_point->value_y_now,1);
}else{
ILI9341_DrawLine(ptr_point->value_x_before,ptr_point->value_y_before,ptr_point->value_x_now,ptr_point->value_y_now,1);
}
}
void GDScream_Data_show(int32_t *data_value , uint16_t data_num){ //GD显示
uint8_t i=0 , j=0 ;
char cStr [ 100 ];
char * pStr = 0;
float ADC_ValueLocal;
int16_t data_value_x , data_value_y ;
for(i=0 ; i<data_num;i++){
ad_point[i].data_value = (int16_t) data_value[i]; //对数据进行模块存储,将采集到的数据一一存入采样点的实时存储寄存器
}
LCD_SetColors(CL_WHITE , CL_WHITE);
if((data_value_x_now<0)||(data_value_x_now > LCD_GDSCAN_X_End-2)){ // 如果是第一次进入最左端存储点就刷新程序
LCD_SetColors(CL_BLACK , CL_WHITE);
ILI9341_DrawRectangle(LCD_GDSCAN_X_Start,
LCD_GDSCAN_Y_Start,
LCD_GDSCAN_X_LENGTH,
LCD_GDSCAN_Y_LENGTH,1,1);
GDScream_Line_Init();
GDScream_Data_show_init();
}
if(data_value_x_before == -1){ //说明是第一次 如果是初始化第一次需要在最左端绘制描绘点
for(i=0 ;i<data_num ;i++ ){
data_value_x = LCD_GDSCAN_X_Start;
data_value_y = LCD_GDSCAN_Y_End -(ad_point[i].data_value/ HY) ;
data_value_x_now = data_value_x ;
data_value_y_now = data_value_y ;
ad_point[i].value_x_now = data_value_x_now;
ad_point[i].value_y_now = data_value_y_now;
LCD_SetColors(ad_point[i].para_color , ad_point[i].para_color);
ad_point[i].draw_point(&ad_point[i]);
//ILI9341_SetPointPixel(ad_point[i].data_value_x_now,ad_point[i].data_value_y_now,1);
data_value_x_before = data_value_x ;
data_value_y_before = data_value_y ;
ad_point[i].value_x_before = data_value_x_before;
ad_point[i].value_y_before = data_value_y_before;
}
}
else {
for(j=0 ;j<data_num ;j++ ){ //正常绘制注意当前数据与之前数据的切换
data_value_x = data_value_x_before+DX ;
data_value_y = LCD_GDSCAN_Y_End -(ad_point[j].data_value/ HY) ;
data_value_x_now = data_value_x ;
data_value_y_now = data_value_y ;
ad_point[j].value_x_now = data_value_x_now;
ad_point[j].value_y_now = data_value_y_now;
LCD_SetColors(ad_point[j].para_color , ad_point[j].para_color);
ad_point[j].draw_point(&ad_point[j]);
//ILI9341_DrawLine(ad_point[j].data_value_x_before,ad_point[j].data_value_y_before,ad_point[j].data_value_x_now,ad_point[j].data_value_y_now,1);
data_value_x_before = data_value_x_now ;
data_value_y_before = data_value_y_now ;
ad_point[j].value_x_before = data_value_x_before;
ad_point[j].value_y_before = data_value_y_before;
}
}
ADC_ValueLocal =(float)ad_point[0].data_value/4096*3.3;
sprintf ( cStr, "0x%04X",ad_point[0].data_value );
LCD_SetColors(CL_MAGENTA,CL_WHITE);
/*选择字体,使用中英文显示时,尽量把英文选择成8*16的字体,
*中文字体大小是16*16的,需要其它字体请自行制作字模*/
/*这个函数只对英文字体起作用*/
LCD_SetFont(&Font8x16);
ILI9341_DispString_EN_CH( LCD_GDControl_X_Start+2 , LCD_GDControl_Y_LENGTH - 50, cStr);
sprintf ( cStr, "%.3fV",ADC_ValueLocal );
LCD_SetColors(CL_RED,CL_WHITE);
/*选择字体,使用中英文显示时,尽量把英文选择成8*16的字体,
*中文字体大小是16*16的,需要其它字体请自行制作字模*/
/*这个函数只对英文字体起作用*/
LCD_SetFont(&Font8x16);
ILI9341_DispString_EN_CH( LCD_GDControl_X_Start +2, LCD_GDControl_Y_LENGTH - 30, cStr);
}
该处使用的url网络请求的数据。