⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd.c

📁 dspic开发控制程序,有助开发pic单片机程序
💻 C
字号:
#include <p30f6014.h>
#include <spi.h>
#include <dsp.h>
#include "common.h"
#include "timers.h"
#include "procsignal.h"
#include "menu.h"
#include "gettime.h"
#include "lcd.h"

#define MAXCHARSPERLINE 20

char PendPos;

static unsigned char TxQueue[256];	////必须定义为256个字节,以便指针ptr绕回。
static volatile unsigned char TxQHead;
static volatile unsigned char TxQTail;
static char PlotBuf[128];
static int PlotPos;
static char PixelSendState;
static char PendDir;
static char CurPendPos;
static char PendTimer;

static const char INPUT_STR[] = "Input Signal";
static const char SYNC_STR[] = "Seconds         Sync";
static const char DATA_STR[] = "Data Bit";

//函数原型
void InitLcd(void);
void CursState(char state);
void WriteChar(char ch);
void Write4Hex(unsigned int val);
void Write2Hex(unsigned char val);
void Write2Dec(unsigned char val);
void WriteDec(unsigned int val);
void ClearLcd(void);
void ClearLcdLine(unsigned char y);
void WriteCStr(const char* ptr);
void SetLcdPos(unsigned char x, unsigned char y );
void PlotTime( int* pBuf );
void ServiceLCD(void);
void PlotPendulum( void );
static void WritePend(char new);
static void PutTxQ(unsigned char val);

// SPI2中断服务子程序
void __attribute__((__interrupt__)) _SPI2Interrupt(void)
{
	if( TxQHead!=TxQTail )
	{
		if( !SPI2STATbits.SPITBF )
		    WriteSPI2( TxQueue[TxQTail++] );
	}
	SPI2STATbits.SPIROV = 0;
	IFS1bits.SPI2IF = 0;
}

//初始化16x2点阵LCD子程序
void InitLcd(void)
{
	TRISGbits.TRISG9 = 0;	//LCD控制器选择行
	PORTGbits.RG0 = 1;
	TxQHead = 0;
	TxQTail = 0;
	CloseSPI2();
	ConfigIntSPI2(SPI_INT_EN & SPI_INT_PRI_3);
	OpenSPI2( FRAME_ENABLE_OFF &
	            ENABLE_SDO_PIN &
	            SPI_MODE16_OFF &
		        SPI_SMP_OFF &
		        SPI_CKE_OFF &
		        SLAVE_ENABLE_OFF &
		        CLK_POL_ACTIVE_HIGH &
		        MASTER_ENABLE_ON &
#if (CLOCK_FREQ == CLOCK_FREQ4XPLL)
		        SEC_PRESCAL_1_1 &		//设定LCD时钟预设值
#else
		        SEC_PRESCAL_2_1 &		
#endif
		        PRI_PRESCAL_64_1,		
				SPI_ENABLE &
	            SPI_IDLE_CON &
	            SPI_RX_OVFLOW_CLR
			);
    LATGbits.LATG9 = 0;
	SemA.PlotActive = 0;
	TimeDelay(2);
    WriteSPI2(0x80);	/复位显示
	TimeDelay(2);
    WriteSPI2(0x80);	/复位显示
	TimeDelay(2);
	PendDir = 1;
	PendPos = 0;
	PendTimer = 0;
}

//把一个字节放到SPI2传输队列子程序
static void PutTxQ(unsigned char val)
{
	DisableIntSPI2;
	TxQueue[TxQHead] = val;
	if( TxQTail == TxQHead++ )
	{
		SPI2STATbits.SPIROV = 0;
		IFS1bits.SPI2IF = 1;	//create fake IRQ to "prime the pump"
	}
	EnableIntSPI2;
}

//清LCD屏幕并设起始点为0子程序
void ClearLcd(void)
{
	PutTxQ(0x82);
}

//光标的状态
void CursState(char state)
{
	if(state==0)
	{
		PutTxQ(0x8B);
	}
	else
	{
	    PutTxQ(0x8C);
	    PutTxQ(0xAD);
	    PutTxQ(0x03);
	}
}

//清LCD的行y子程序
void ClearLcdLine(unsigned char y)
{
    PutTxQ(0xA9);
    PutTxQ(y);
}


//在当前光标位置写一个字符子程序
void WriteChar(char ch)
{
    PutTxQ(0xA8);
    PutTxQ(ch);
}

//写钟摆的位置
static void WritePend(char newpos)
{
    PutTxQ(0xE6);
    PutTxQ(' ');
    PutTxQ(CurPendPos);
    PutTxQ(3);
//
    PutTxQ(0xE6);
	if( (0==newpos) || (19==newpos) )
	    PutTxQ('*');
	else
	    PutTxQ('-');
    PutTxQ(newpos);
    PutTxQ(3);
}

//在当前光标位置写一个常字符串子程序
void WriteCStr(const char* ptr)
{
unsigned int i=0;
char ch;
	do
	{
		ch = ptr[i++];
		if(ch==0)
			break;
		else
			WriteChar(ch);
	}while(i<MAXCHARSPERLINE);
}

//在LCD上把一个数值写为4个16进制格式子程序
void Write4Hex(unsigned int val)
{
char ch;
	ch = (val>>12);
	if(ch<=9)
		ch += '0';
	else
		ch += 'A' - 10;
	WriteChar(ch);
	ch = (val>>8) & 0x0F;
	if(ch<=9)
		ch += '0';
	else
		ch += 'A' - 10;
	WriteChar(ch);
	ch = (val>>4) & 0x0F;
	if(ch<=9)
		ch += '0';
	else
		ch += 'A' - 10;
	WriteChar(ch);
	ch = val & 0x0F;
	if(ch<=9)
		ch += '0';
	else
		ch += 'A' - 10;
	WriteChar(ch);
}

//在LCD上把一个数值写为2个16进制格式子程序
void Write2Hex(unsigned char val)
{
char ch;
	ch = val>>4;
	if(ch<=9)
		ch += '0';
	else
		ch += 'A' - 10;
	WriteChar(ch);
	ch = val & 0x0F;
	if(ch<=9)
		ch += '0';
	else
		ch += 'A' - 10;
	WriteChar(ch);
}

//在LCD上把一个数值写为10进制格式子程序
void Write2Dec(unsigned char val)
{
char ch;
	ch = val/10;
	val = val - 10*ch;
	ch += '0';
	WriteChar(ch);
	ch = val;
	ch += '0';
	WriteChar(ch);
}

//在LCD上把一个数值写为10进制格式子程序
void WriteDec(unsigned int val)
{
char ch;
unsigned int tmp;
	tmp = val;
	ch = tmp/10000;
	tmp = tmp - 10000*ch;
	ch += '0';
	WriteChar(ch);
	ch = tmp/1000;
	tmp = tmp - 1000*ch;
	ch += '0';
	WriteChar(ch);
	ch = tmp/100;
	tmp = tmp - 100*ch;
	ch += '0';
	WriteChar(ch);
	ch = tmp/10;
	tmp = tmp - 10*ch;
	ch += '0';
	WriteChar(ch);
	ch = tmp;
	ch += '0';
	WriteChar(ch);
}

//设定LCD的坐标子程序
void SetLcdPos(unsigned char x, unsigned char y )
{
    PutTxQ(0xC5);
    PutTxQ(x);
    PutTxQ(y);
}

//画钟摆子程序
void PlotPendulum( void )
{
	if(++PendTimer == 5)	// 50Hz分为10Hz
	{
		PendTimer = 0;
		if(PendPos>19)		  //处理方向改变
			PendDir = -1;
		else				        
			if(PendPos<0)
				PendDir = +1;
			else
				if(MENU_MAIN == CurrentMenu)
				{
					WritePend(PendPos);
					CurPendPos = PendPos;
				}
		PendPos = CurPendPos+PendDir;
	}
}

//画时间函数
void PlotTime( int* pBuf )
{
int x;
int z;
	if(!SemA.PlotActive)
	{
		if(0==LCDHoldoffCounter)
		{
			if(CurrentMenu==MENU_SIGNAL)
			{
				for(x=0; x<122; x++)
					PlotBuf[x] = (char)(16 + (pBuf[x]>>11) );
		    	PutTxQ(0x82);	//清屏
				SetLcdPos(0,0);		
				WriteCStr(INPUT_STR);//画字符
				PlotPos = 0;		
				PixelSendState = 0;
				SemA.PlotActive = 1;		//使能LCD画状态机
				LCDHoldoffCounter = 4;
			}
			else if( SemA.SecRdy)
			{
		    	PutTxQ(0x82);	//清屏
				if( CurrentMenu==MENU_SYNC)
				{
					z = 150 - (122/2);
					for(x=0; x<122; x++)
					{
						PlotBuf[x] = (char)( (SecSyncBuf[z]>>9) );
						if(++z >= 150)
							z = 0;
					}
					SetLcdPos(0,0);		//画字符
					WriteCStr(SYNC_STR);
				}
				else if( CurrentMenu==MENU_DATA )
				{
					for(x=0; x<122; x++)
						PlotBuf[x] = (char)( (RawDataBuf[x/4]>>7) );
					SetLcdPos(12,0);		//画字符
					WriteCStr(DATA_STR);
				}
				PlotPos = 0;		
				PixelSendState = 0;
				SemA.PlotActive = 1;		//使能LCD画状态机
				LCDHoldoffCounter = 4;
			}
		}
	}
}

//LCD画点子程序
void ServiceLCD( )
{
    if( (TxQTail == TxQHead ) && SemA.PlotActive )	
	{											
		PixelSendState++;
		if( PixelSendState==1 )
		{
	    	PutTxQ(0xD8);			//像素开命令
		}
		else if( PixelSendState==2 )
		{
	    	PutTxQ(PlotPos );		//像素 x 位置写
		}
		else
		{
	    	PutTxQ(PlotBuf[PlotPos++] );
			PixelSendState = 0;			//像素 y 位置写
		}
		if(PixelSendState>=3)
			PixelSendState = 0;
		if( PlotPos>=122 )
	    	SemA.PlotActive = 0;	
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -