0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32F103双重ADC同步规则模式采集实验

王琪 来源:pgph 作者:pgph 2022-02-24 10:47 次阅读

双重 ADC 同步规则模式采集实验与多路LCD 波形示波器制作显示,本文展示了STM32 AD 双重 ADC 同步规则模式采集实验。

内容涉及 :

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 的工作具体如下

AD转换包括采样阶段和转换阶段,在采样阶段才对通道数据进行采集;

而在转换阶段只是将采集到的数据进行转换为数字量输出,此刻通道数据变化不会改变转换结果。

独立模式的 ADC 采集需要在一个通道采集并且转换完成后才会进行下一个通道的采集。

而双重 ADC 的机制就是使用两个 ADC 同时采样一个或者多个通道。

双重 ADC 模式较独立模式一个最大的优势就是提高了采样率,弥补了单个 ADC 采样不够快的缺点。

启用双 ADC模式的时候,通过配置 ADC_CR1寄存器的 DUALMOD[3:0]位,可以有几种不同的模式,具体见表格 31-1

模式 简要说明
同步注入模式 ADC1和ADC2同时转换一个注入通道组,其中ADC1为主,ADC2为从。转换的数据存储在每个 ADC 接口的 ADC_JDRx 寄存器中。
同步规则模式 ADC1 和 ADC2 同时转换一个规则通道组,其中 ADC1 为主,ADC2 为从。
ADC1 转换的结果放在 ADC1_DR 的低 16 位,ADC2 转换的结果放在 ADC1_DR 的高十六位。
快速交叉模式 ADC1 和 ADC2 交替采集一个规则通道组(通常为一个通道)。当ADC2 触发之后,ADC1 需要等待 7 个 ADCCLK 之后才能触发。
慢速交叉模式 ADC1 和 ADC2 交替采集一个规则通道组(只能为一个通道)。当ADC2 触发之后,ADC1 需要等待 14 个 ADCCLK 之后才能触发。

三:代码分析

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  
#include 

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 ;itouch_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;ivalue_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 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;i++){>

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 示波器
    +关注

    关注

    113

    文章

    6239

    浏览量

    184779
  • adc
    adc
    +关注

    关注

    98

    文章

    6494

    浏览量

    544427
  • 内存
    +关注

    关注

    8

    文章

    3017

    浏览量

    73993
收藏 人收藏

    评论

    相关推荐

    STM32F103×8/STM32F103×B MCU手册

    1. Q: STM32F103C8T6如何正确配置时钟系统?A: STM32F103C8T6的时钟系统配置通常涉及HSE(高速外部时钟)、HSI(高速内部时钟)、PLL(相位锁定环)等。配置时,首先
    发表于 11-18 15:14 0次下载

    STM32F407三ADC采样设置死机怎么解决?

    使用STM32F407三ADCADC1ADC2 ADC3分别分配8个通道(ADC1 把芯片测
    发表于 07-26 06:43

    CKS32F107xx系列MCU的双重ADC模式

    独立模式ADC采集需要在一个通道采集并且转换完成后才会进行下一个通道的采集。而双重
    的头像 发表于 07-22 09:19 462次阅读
    CKS32<b class='flag-5'>F</b>107xx系列MCU的<b class='flag-5'>双重</b><b class='flag-5'>ADC</b><b class='flag-5'>模式</b>

    STM32F103xC,STM32F103xD,STM32F103xE中文资料

    电子发烧友网站提供《STM32F103xC,STM32F103xD,STM32F103xE中文资料.pdf》资料免费下载
    发表于 06-17 14:12 3次下载

    STM32F103进入睡眠模式或者待机模式或者停机模式,IO脚原先设置的电平值是否会改变?

    STM32F103进入睡眠模式或者待机模式或者停机模式,IO脚原先设置的电平值是否会改变? 锁定STM32F103的IO脚,那么当
    发表于 05-17 09:22

    stm32f302和stm32f103ADC区别是什么?

    请问stm32f302和stm32f103ADC除了stm32f103有2个ADCADC1和
    发表于 05-15 08:03

    关于STM32F103使用FSMC同步模式问题求解

    大家好,我现在正在使用STM32F103的FSMC同步模式。 需要读取高速ADC数据,ADC是8位并口,但需要一个时钟去触发转换,在时钟上升
    发表于 04-17 08:13

    如何减少STM32F103 ADC采集时间?

    环境: STM32CubeMX 5.6.1(库为:STM32F11.8.0) IAR for ARM 8.40.2 STM32F103C8T6 BluePill 问题: 使用PA1~PA4进行4
    发表于 04-10 08:20

    stm32f103ADC同步规则模式两个ADC转换的通道数量能不一样吗?

    stm32f103rct6,配置成双ADC同步规则模式时,主ADC1、从
    发表于 04-10 06:21

    STM32F103采集模拟量只要低于3.3V,采集的值就是0怎么解决?

    利用STM32F103 ADC直接采集模拟量,现场返修板出现的问题。 采集电压引脚不论是多少,只要低于3.3V,通过keil仿真直接观察ADC
    发表于 04-08 07:24

    想用STM32F373的三个SDADC同步采集电压信号,DMA是工作在什么模式?怎么配置?

    我想用STM32F373的三个SDADC同步采集电压信号,请问如果要搭配DMA工作,DMA是工作在什么模式?怎么配置?(没有看到像F4系列的
    发表于 03-28 06:49

    STM32F407的规则同步ADC采集如何实现256k采样+转换速度?

    F407的规则同步ADC采集如何 实现256k采样+转换速度?
    发表于 03-07 07:51

    ARM系列STM32F103芯片的解密方法

    本文介绍ARM系列STM32F103芯片的解密方法,其内核是Cortex-M3,内存从16K-512K都有。
    发表于 02-28 11:20 1664次阅读

    stm32f103 flash模拟eeprom

    STM32F103是意法半导体(STMicroelectronics)推出的一款32位单片机系列,该系列芯片具有高性能和丰富的外设接口,广泛应用于工业控制、消费电子、汽车电子等领域。其中
    的头像 发表于 01-09 11:21 2015次阅读

    请问adxrs620输出范围怎么调理到适合stm32f103adc量程?

    adxrs620输出范围怎么调理到适合stm32f103adc量程了?stm32f103是3.3v供电的。620输出我想加一级rc的滤波带宽控制在300hz内即可。
    发表于 01-02 07:23