找回密码
 立即注册
查看: 221|回复: 0

15系列单片机与迪文DGUS屏应用之(六):单片机程序编写

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:41
  • 最近打卡:2025-06-16 09:10:33

29

主题

14

回帖

411

积分

中级会员

积分
411
发表于 2025-5-5 21:00:24 | 显示全部楼层 |阅读模式

相信接触过STC15系列单片机的小伙伴们,应该会对其编程风格比较熟悉,没错,STC15系列单片机可以采用库函数编程,官方提供了标准的函数库,我们只需要利用好库函数,便可大大简化配置流程,从而提高编程效率。由于笔者这里的教程不是关于51单片机的基础教程,所以此处省去了新建工程以及如何添加库文件等操作。

首先,我们要养成良好的习惯,在使用任何一款板子的时候,先建一个配置板载资源的文件,当然要是板子比较复杂的话,可以分模块配置多个,由于笔者使用的板子比较简单,所以就只添加了为“bsp_gpio.h”和“bsp_gpio.c”的文件,顾名思义,就是一些输入输出的配置而已了。

#ifndef	__BSP_GPIO_H__
#define	__BSP_GPIO_H__

#include	"GPIO.h"

/****************** ADC GPIO ******************/
//ADC0 - ADC1

#define ADC0_GPIO_PIN              GPIO_Pin_1
#define ADC0_GPIO                  GPIO_P1

#define ADC1_GPIO_PIN              GPIO_Pin_0
#define ADC1_GPIO                  GPIO_P1

/****************** 输出GPIO ******************/
//Y00 - Y05
#define Y00                        P37
#define Y00_GPIO_PIN               GPIO_Pin_7
#define Y00_GPIO                   GPIO_P3

#define Y01                        P36
#define Y01_GPIO_PIN               GPIO_Pin_6
#define Y01_GPIO                   GPIO_P3

#define Y02                        P35
#define Y02_GPIO_PIN               GPIO_Pin_5
#define Y02_GPIO                   GPIO_P3

#define Y03                        P34
#define Y03_GPIO_PIN               GPIO_Pin_4
#define Y03_GPIO                   GPIO_P3

#define Y04                        P33
#define Y04_GPIO_PIN               GPIO_Pin_3
#define Y04_GPIO                   GPIO_P3

#define Y05                        P32
#define Y05_GPIO_PIN               GPIO_Pin_2
#define Y05_GPIO                   GPIO_P3

//X00 - X07
#define X00                        P12
#define X00_GPIO_PIN               GPIO_Pin_2
#define X00_GPIO                   GPIO_P1

#define X01                        P13
#define X01_GPIO_PIN               GPIO_Pin_3
#define X01_GPIO                   GPIO_P1

#define X02                        P14
#define X02_GPIO_PIN               GPIO_Pin_4
#define X02_GPIO                   GPIO_P1

#define X03                        P15
#define X03_GPIO_PIN               GPIO_Pin_5
#define X03_GPIO                   GPIO_P1

#define X04                        P16
#define X04_GPIO_PIN               GPIO_Pin_6
#define X04_GPIO                   GPIO_P1

#define X05                        P17
#define X05_GPIO_PIN               GPIO_Pin_7
#define X05_GPIO                   GPIO_P1

#define X06                        P54
#define X06_GPIO_PIN               GPIO_Pin_4
#define X06_GPIO                   GPIO_P5

#define X07                        P55
#define X07_GPIO_PIN               GPIO_Pin_5
#define X07_GPIO                   GPIO_P5

#define Input_ON                   0   //输入ON
#define Input_OFF                  1   //输入OFF

#define OutputT_ON                 1   //晶体管输出ON
#define OutputT_OFF                0   //晶体管输出OFF

void GPIO_Config(void);

#endif

接下来,我们来配置一下串口参数,在之前的帖子中我们知道,迪文DGUS屏的串口通信波特率配置的是115200,那么,我们在单片机程序中,自然也要讲串口通信的波特率配置成115200,其他的就不需要修改了:

#include	"bsp_usart.h"

/***************  串口初始化函数 *****************/
void UART_config(void)
{
    COMx_InitDefine		COMx_InitStructure;					//结构定义
  
	COMx_InitStructure.UART_Mode      = UART_8bit_BRTx;		//模式,       UART_ShiftRight,UART_8bit_BRTx,UART_9bit,UART_9bit_BRTx
	COMx_InitStructure.UART_BRT_Use   = BRT_Timer2;			//使用波特率,   BRT_Timer1, BRT_Timer2 (注意: 串口2固定使用BRT_Timer2)
	COMx_InitStructure.UART_BaudRate  = 115200ul;			//波特率, 一般 110 ~ 115200
	COMx_InitStructure.UART_RxEnable  = ENABLE;				//接收允许,   ENABLE或DISABLE
	COMx_InitStructure.UART_Interrupt = ENABLE;				//中断允许,   ENABLE或DISABLE
	COMx_InitStructure.UART_P_SW      = UART1_SW_P30_P31;	//切换端口,   UART1_SW_P30_P31,UART1_SW_P36_P37,UART1_SW_P16_P17(必须使用内部时钟)

    USART_Configuration(USART1, &COMx_InitStructure);		//初始化串口1 USART1,USART2
}

程序中有需要用到串口定时向触摸屏刷新数据,所以,这里我们也配置一个定时器,并设置起中断频率为1000Hz,即:1ms中断一次。

#include	"bsp_timer.h"

/************************ 定时器配置 ****************************/
void	Timer0_config(void)
{
	TIM_InitTypeDef		TIM_InitStructure;						//结构定义
  
	TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;	    //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
	TIM_InitStructure.TIM_Polity    = PolityLow;			    //指定中断优先级(低到高) Polity_0,Polity_1,Polity_2,Polity_3
	TIM_InitStructure.TIM_Interrupt = ENABLE;					//中断是否允许,   ENABLE或DISABLE
	TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;		        //指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
	TIM_InitStructure.TIM_ClkOut    = DISABLE;				    //是否输出高速脉冲, ENABLE或DISABLE
	TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / 1000);		//初值,
	TIM_InitStructure.TIM_Run       = ENABLE;					//是否初始化后启动定时器, ENABLE或DISABLE
	Timer_Inilize(Timer0,&TIM_InitStructure);					//初始化Timer0	  Timer0,Timer1,Timer2,Timer3,Timer4
}

接下来,我们需要根据板子上的IO分布,来配置一下IO口的输入输出模式,所有输入口均配置成“准双向口”,所有输出口均配置成“强推挽模式”。

#include	"bsp_gpio.h"

/************************ IO口配置 ****************************/
void GPIO_Config(void)
{
	GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义
  
    //P10-11口设置为高阻输入
	GPIO_InitStructure.Pin  = ADC0_GPIO_PIN;    //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_HighZ;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(ADC0_GPIO,&GPIO_InitStructure);//初始化
  
    GPIO_InitStructure.Pin  = ADC1_GPIO_PIN;    //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7, 或操作
	GPIO_InitStructure.Mode = GPIO_HighZ;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(ADC1_GPIO,&GPIO_InitStructure);//初始化
  
    //Y00
    GPIO_InitStructure.Pin  = Y00_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_OUT_PP;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(Y00_GPIO,&GPIO_InitStructure); //初始化 
  
    //Y01
    GPIO_InitStructure.Pin  = Y01_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_OUT_PP;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(Y01_GPIO,&GPIO_InitStructure); //初始化 
  
    //Y02
    GPIO_InitStructure.Pin  = Y02_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_OUT_PP;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(Y02_GPIO,&GPIO_InitStructure); //初始化 
  
    //Y03
    GPIO_InitStructure.Pin  = Y03_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_OUT_PP;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(Y03_GPIO,&GPIO_InitStructure); //初始化 
  
    //Y04
    GPIO_InitStructure.Pin  = Y04_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_OUT_PP;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(Y04_GPIO,&GPIO_InitStructure); //初始化 
  
    //Y05
    GPIO_InitStructure.Pin  = Y05_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_OUT_PP;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(Y05_GPIO,&GPIO_InitStructure); //初始化 
  
    //X00
    GPIO_InitStructure.Pin  = X00_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(X00_GPIO,&GPIO_InitStructure); //初始化 
  
    //X01
    GPIO_InitStructure.Pin  = X01_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(X01_GPIO,&GPIO_InitStructure); //初始化 
  
    //X02
    GPIO_InitStructure.Pin  = X02_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(X02_GPIO,&GPIO_InitStructure); //初始化 
  
    //X03
    GPIO_InitStructure.Pin  = X03_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(X03_GPIO,&GPIO_InitStructure); //初始化 
  
    //X04
    GPIO_InitStructure.Pin  = X04_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(X04_GPIO,&GPIO_InitStructure); //初始化 
  
    //X05
    GPIO_InitStructure.Pin  = X05_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(X05_GPIO,&GPIO_InitStructure); //初始化 
  
    //X06
    GPIO_InitStructure.Pin  = X06_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(X06_GPIO,&GPIO_InitStructure); //初始化 
  
    //X07
    GPIO_InitStructure.Pin  = X07_GPIO_PIN;	    //指定要初始化的IO
	GPIO_InitStructure.Mode = GPIO_PullUp;		//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
	GPIO_Inilize(X07_GPIO,&GPIO_InitStructure); //初始化 
   
    Y00 = OutputT_OFF;
    Y01 = OutputT_OFF;
    Y02 = OutputT_OFF;
    Y03 = OutputT_OFF;
    Y04 = OutputT_OFF;
    Y05 = OutputT_OFF;
}

另外,程序中也有用到两路0-5V电压的采集,所以此处我们还需要对ADC相关的参数进行配置,本例程中采用的是AD口分别是P10和P11,查询方式获取AD值:

#include	"bsp_adc.h"

/**************** ADC配置函数 *****************/
/*P11 ADC0
/*P10 ADC1
/**********************************************/
void    ADC_config(void)
{
	ADC_InitTypeDef		ADC_InitStructure;				//结构定义
  
	ADC_InitStructure.ADC_Px        = ADC_P11|ADC_P10;	//设置要做ADC的IO,	ADC_P10 ~ ADC_P17(或操作),ADC_P1_All
	ADC_InitStructure.ADC_Speed     = ADC_90T;			//ADC速度			ADC_90T,ADC_180T,ADC_360T,ADC_540T
	ADC_InitStructure.ADC_Power     = ENABLE;		    //ADC功率允许/关闭	ENABLE,DISABLE
	ADC_InitStructure.ADC_AdjResult = ADC_RES_H2L8;	    //ADC结果调整,	ADC_RES_H2L8,ADC_RES_H8L2
	ADC_InitStructure.ADC_Polity    = PolityLow;		//优先级设置	PolityHigh,PolityLow
	ADC_InitStructure.ADC_Interrupt = DISABLE;			//中断允许		ENABLE,DISABLE
	ADC_Inilize(&ADC_InitStructure);					//初始化
  
	ADC_PowerControl(ENABLE);							//单独的ADC电源操作函数, ENABLE或DISABLE
}


至此,系统配置相关的东西基本就完成了,接下来,我们就需要自己写一些应用相关的函数了,本例中,笔者写了3个函数:

• Uart_Driver(); //串口1驱动函数
• ADC_Sampling(); //ADC采样
• GIOP_StateRefresh();//GPIO状态刷新

其中,Uart_Driver()函数,主要是用对串口中断接收到的数据进行解析及定时发送数据,其中解析数据主要包括:DGUS屏按键返回的指令、参数设置的指令等;定时发送数据内容主要包括:定时向DGUS屏写入数据,比如:数据变量显示、图标变量显示等; ADC_Sampling()函数主要是对外部两路0-5V模拟量输入进行采样处理;
GIOP_StateRefresh()函数主要是用来实时刷新输入输出口的状态。

那么,我们首先来看下Uart_Driver()函数:

/*********************   UART数据处理  **********************/
void Uart_Driver(void)
{
    if(Uart1_RX_Finish)
    {
        //根据收到的指令执行相应的动作
        if((RX1_Buffer[0]==0x06)&&(RX1_Buffer[1]==0X83)&&(RX1_Buffer[2]==0x00)&&
           (RX1_Buffer[3]==0x20)&&(RX1_Buffer[4]==0x01)&&(RX1_Buffer[5]==0x00))//按键返回
        {
            if(RX1_Buffer[6]==0x01)//Y0
            {
                Y00 = ~Y00;
            }
            if(RX1_Buffer[6]==0x02)//Y1
            {
                Y01 = ~Y01;
            }
            if(RX1_Buffer[6]==0x03)//Y2
            {
                Y02 = ~Y02;
            }
            if(RX1_Buffer[6]==0x04)//Y3
            {
                Y03 = ~Y03;
            }
            if(RX1_Buffer[6]==0x05)//Y4
            {
                Y04 = ~Y04;
            }
            if(RX1_Buffer[6]==0x06)//Y5
            {
                Y05 = ~Y05;
            }
        }
        //定时器返回数据:0-99999ms
        if((RX1_Buffer[0]==0x08)&&(RX1_Buffer[1]==0X83)&&(RX1_Buffer[2]==0x00)&&(RX1_Buffer[3]==0x10)&&(RX1_Buffer[4]==0x02))//按键返回
        {
            SetTime    = (u32)RX1_Buffer[5]<<24|(u32)RX1_Buffer[6]<<16|(u32)RX1_Buffer[7]<<8|(u32)RX1_Buffer[8];
            SetTimeDis = SetTime;
        
            EEPROM_SectorErase(IAP_ADDRESS);//扇区擦除,为写EEPROM做准备

            EEPROM_WriteTable[0] = SetTime>>24;
            EEPROM_WriteTable[1] = SetTime>>16;
            EEPROM_WriteTable[2] = SetTime>>8 ;
            EEPROM_WriteTable[3] = SetTime;
   
            EEPROM_WriteTable[4] = 0x01;    //参数更新标志
        
            EEPROM_write_n(IAP_ADDRESS,EEPROM_WriteTable,5);//将数据写到EEPROM
        }
    
        memset(RX1_Buffer,NULL,sizeof(RX1_Buffer));//清空RX1_Buffer数组
    
        Uart1_RX_Finish = 0;
    }
  
    if(Uart1_TX_EN)//每隔指定时间发送一次数据
    {
        if(!RX_Busy)
        {
            if(!Uart1_TX_Init)
            {
                TX1_Buffer[0]  = 0x5A;//帧头
                TX1_Buffer[1]  = 0xA5;//帧头
                TX1_Buffer[2]  = 0x27;//长度
                TX1_Buffer[3]  = 0x82;//命令0x82
            
                TX1_Buffer[4]  = 0x00;//首地址H
                TX1_Buffer[5]  = 0x00;//首地址L
            
                TX1_Buffer[6]  = 0x00;          //X0输入状态H
                TX1_Buffer[7]  = (u8)X00_State; //X0输入状态L
            
                TX1_Buffer[8]  = 0x00;          //X1输入状态H
                TX1_Buffer[9]  = (u8)X01_State; //X1输入状态L
            
                TX1_Buffer[10] = 0x00;          //X2输入状态H
                TX1_Buffer[11] = (u8)X02_State; //X2输入状态L
            
                TX1_Buffer[12] = 0x00;          //X3输入状态H
                TX1_Buffer[13] = (u8)X03_State; //X3输入状态L
            
                TX1_Buffer[14] = 0x00;          //X4输入状态H
                TX1_Buffer[15] = (u8)X04_State; //X4输入状态L
            
                TX1_Buffer[16] = 0x00;          //X5输入状态H
                TX1_Buffer[17] = (u8)X05_State; //X5输入状态L
            
                TX1_Buffer[18] = 0x00;          //X6输入状态H
                TX1_Buffer[19] = (u8)X06_State; //X6输入状态L
            
                TX1_Buffer[20] = 0x00;          //X7输入状态H
                TX1_Buffer[21] = (u8)X07_State; //X7输入状态L
            
                TX1_Buffer[22] = 0x00;          //Y0输出状态H
                TX1_Buffer[23] = (u8)Y00_State; //Y0输出状态L
            
                TX1_Buffer[24] = 0x00;          //Y1输出状态H
                TX1_Buffer[25] = (u8)Y01_State; //Y1输出状态L
            
                TX1_Buffer[26] = 0x00;          //Y2输出状态H
                TX1_Buffer[27] = (u8)Y02_State; //Y2输出状态L
            
                TX1_Buffer[28] = 0x00;          //Y3输出状态H
                TX1_Buffer[29] = (u8)Y03_State; //Y3输出状态L
            
                TX1_Buffer[30] = 0x00;          //Y4输出状态H
                TX1_Buffer[31] = (u8)Y04_State; //Y4输出状态L
            
                TX1_Buffer[32] = 0x00;          //Y5输出状态H
                TX1_Buffer[33] = (u8)Y05_State; //Y5输出状态L
            
                TX1_Buffer[34] = ADC0_Voltage/256;//ADC0电压H
                TX1_Buffer[35] = ADC0_Voltage%256;//ADC0电压L
            
                TX1_Buffer[36] = ADC1_Voltage/256;//ADC1电压H
                TX1_Buffer[37] = ADC1_Voltage%256;//ADC1电压L
            
                TX1_Buffer[38] = SetTimeDis>>24;          //定时时间HH
                TX1_Buffer[39] = (SetTimeDis>>16)&0x00FF; //定时时间HL
                TX1_Buffer[40] = (SetTimeDis>>8)&0x0000FF;//定时时间LH
                TX1_Buffer[41] = SetTimeDis%256;          //定时时间LL
            
                Uart1_TX_Init  = 1;
                COM1.TX_write  = 0;
            }
        
            if(COM1.TX_write<42)
            {
                if(COM1.B_TX_busy == 0)
                {
                    COM1.B_TX_busy = 1;
                    SBUF = TX1_Buffer[COM1.TX_write++];        //发送接收到的字符
                }
            }
            else
            {
                COM1.RX_Cnt     = 0;
                Uart1_TX_EN     = 0;//数据发送完成,uart1发送数据使能清“0”
            }
        }
    }
}

在这个函数中,主要是串口中断完成数据接收后,对其中两条指令进行解析,第一条指令是关于DGUS屏的点动控制,也就是实现前面介绍的功能,在DGUS屏上,点击Y0按键,板子对应的Y00口输出ON,状态图标变成绿色;再一次点击Y00按键,板子对应的Y00口输出OFF,状态图标变成红色,其他按键及板子上的输出口也按照同样的逻辑执行。

第二条指令,就是一条关于时间参数设置的指令,通过触摸屏设置一个时间参数,下发到单片机,可用过某些应用场合下定时用,比如,定时让一个LED输出ON、OFF,从而实现闪烁效果等。

关于这两条指令每个字节的含义,在前面建DGUS工程时也有说明,在此就不再赘述。

这个串口发送数据的时间间隔可以通过触摸屏设置,这个定时时间是通过定时器0来实现的:

/********************* Timer0中断函数************************/
void timer0_int (void) interrupt TIMER0_VECTOR //1ms
{
    adc_msec  ++;
    uart_msec ++;
  
    if(uart_msec>=SetTime)//串口间隔轮询
    {
        Uart1_TX_EN   = 1;
        Uart1_TX_Init = 0;
        uart_msec     = 0;
    }
}

同时,在这个定时器中断函数中,还设定了AD采用的时间间隔,即:100ms进行一次AD采样,然后,为了能让采集到的数据更准确一点,我们通过多次采样求平均值的方式进行处理,当然,还有更多更好的方式,笔者能力有限,也就不好献丑了,在此只给大家提供一个比较简单的处理方式。

/*********************     ADC采样     **********************/
void ADC_Sampling(void)
{
    if(adc_msec>=100)         //每隔100ms采集一次AD数据
    {
        adc_msec = 0;
    
        ADC0_VALUE_TEMP += Get_ADC10bitResult(1);//通道1-P11
        ADC1_VALUE_TEMP += Get_ADC10bitResult(0);//通道0-P10
    
        if(++adc_count>=10)//采集10次数据,求平均值
        {
            ADC0_VALUE   = ADC0_VALUE_TEMP/10;      //求出ADC0的AD平均值
            ADC1_VALUE   = ADC1_VALUE_TEMP/10;      //求出ADC1的AD平均值
        
            //将得到的AD值换算成电压值(单位:mV)
            ADC0_Voltage = (ADC0_VALUE*5000UL)/1024; //求出ADC0的电压值,单位mV
            ADC1_Voltage = (ADC1_VALUE*5000UL)/1024; //求出ADC1的电压值,单位mV
        
            ADC0_VALUE_TEMP = 0;
            ADC1_VALUE_TEMP = 0;
        
            adc_count       = 0;
        }
    }
}

最后一个函数,就是GIOP_StateRefresh()IO状态刷新的函数了,这里主要是通过一个比较简单方法,来获取当前板子上的一些输入输出状态,然后通过串口发送到DGUS屏显示。

/*********************    IO状态刷新   **********************/
void GIOP_StateRefresh(void)
{
    //输入状态刷新
    if(X00)X00_State  = 0;else X00_State = 1;
    if(X01)X01_State  = 0;else X01_State = 1;
    if(X02)X02_State  = 0;else X02_State = 1;
    if(X03)X03_State  = 0;else X03_State = 1;
    if(X04)X04_State  = 0;else X04_State = 1;
    if(X05)X05_State  = 0;else X05_State = 1;
    if(X06)X06_State  = 0;else X06_State = 1;
    if(X07)X07_State  = 0;else X07_State = 1;
  
    //输出状态刷新
    if(!Y00)Y00_State = 0;else Y00_State = 1;
    if(!Y01)Y01_State = 0;else Y01_State = 1;
    if(!Y02)Y02_State = 0;else Y02_State = 1;
    if(!Y03)Y03_State = 0;else Y03_State = 1;
    if(!Y04)Y04_State = 0;else Y04_State = 1;
    if(!Y05)Y05_State = 0;else Y05_State = 1;
}

笔者能力有限,所以在本例中使用的都是一些比较笨的办法,但是笔者相信大家肯定会有更多更好的办法来实现该项目的功能,欢迎大家站内私信或者向直接通过论坛问答频道向笔者提问。

最后,也就是本项目中比较关键的一个知识点,那就是关于DGUS屏的指令的接收处理,在前面介绍有介绍过迪文DGUS屏的指令构成:

6-12.png

本例中,DGUS工程配置的时候,就将帧头设置成了5A A5,由于没有启用CRC校验,因此,我们也不需要关注CRC校验。对于接收迪文DGUS指令的思路是这样的:

先判断帧头,如果帧头验证成功了,就意味着是DGUS屏在下发指令,接下来,就要判断数据的长度,所以这个长度位Len就要起到比较关键的作用了,这个长度位Len本身就是指后面跟随数据的总长度,因为,我们只需要在接收到Len个数据后,就可以认为是接收完成了,而后即时在接收到数据也不管了。当然,除非后面的数据又是以5A A5开头的,也就意味着是一帧新的数据的到来。

/********************* UART1中断函数 ************************/
void UART1_int (void) interrupt UART1_VECTOR
{
	static bit RX_5A_OK = 0;
    static bit RX_A5_OK = 0;
    static u8  UART1_DataTemp = 0;
  
    if(RI)
	{
		RI = 0;
    
        UART1_DataTemp = SBUF;
        RX_Busy 	   = 1;	//接收忙
    
        if(RX_5A_OK)
		{
			if(RX_A5_OK)
			{
				RX1_Buffer[COM1.RX_Cnt++] = UART1_DataTemp;      //将接收到的数组暂存到RX1_Buffer数组
		
				if(COM1.RX_Cnt == RX1_Buffer[0] + 1)			 //接收完成
				{
					Uart1_RX_Finish = 1;			             //数据接收完成,将标志位置1 
					RX_5A_OK	 	= 0;
					RX_A5_OK	 	= 0;
                    RX_Busy 	    = 0;	//接收忙清零
				}
			}
			else
			{
				if(UART1_DataTemp == 0xA5)
				{
					RX_A5_OK 		= 1;
					COM1.RX_Cnt 	= 0;
				}
			}
		}
		else 
		{
			if(UART1_DataTemp == 0x5A)
			{
				RX_5A_OK = 1;
			}
		}
    
        if(COM1.RX_Cnt >= COM_RX1_Lenth)	COM1.RX_Cnt = 0;
	}

	if(TI)
	{
		TI = 0;
        COM1.B_TX_busy = 0;
	}
}


在串口接收数据完成之后,会让一个变量Uart1RXFinish置1,然后再Uart1_Monitor()函数中,一旦检测到Uart1RXFinish为1后,就开始解析数据,解析完成后,将标志位Uart1RXFinish清零。这样一来,就实现了对DGUS屏指令的接收及解析。

00.png

至此,整个项目就完成了,只需把代码下载到板子中,并将板子跟DGUS屏连接起来,就能看到项目要实现的效果了。在后续的操作文章中,笔者将会给大家介绍更多DGUS屏和单片机的相关操作,敬请期待!

本帖被以下淘专辑推荐:

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-17 05:34 , Processed in 0.112902 second(s), 52 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表