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

📄 lcd.c

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

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

static const char TIME_STR[] = "Time";
static const char FREQ_STR[] = "Freq";

//函数原型
void InitLcd(void);
void WriteChar(char ch);
void Write4Hex(unsigned int val);
void Write2Hex(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);
static void PutTxQ(unsigned char val);

// SPI2中断服务子程序
void __attribute__((__interrupt__)) _SPI2Interrupt(void)
{
	if( TxQHead!=TxQTail )
	{
		if( !SPI2STATbits.SPITBF )
		{
		    WriteSPI2( TxQueue[TxQTail++] );
			TxQTail &= 0x7F;	//处理指针ptr绕回
		}
	}
	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;
	Sem.PlotActive = 0;
	TimeDelay(2);
    PutTxQ(0x80);	//复位显示
	TimeDelay(2);
    PutTxQ(0x80);	//复位显示
	TimeDelay(2);
    PutTxQ(0x80);	//复位显示
	TimeDelay(2);
    PutTxQ(0x80);	//复位显示
	TimeDelay(2);
    PutTxQ(0x80);	//复位显示
	TimeDelay(2);
	ClearLcd();
}

//把一个字节放到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"
	}
	TxQHead &= 0x7F;	//deal with ptr wrap around
	EnableIntSPI2;
}

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

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

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

//在当前光标位置写一个常字符串子程序
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 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 PlotTime( int* pBuf )
{
int x;
	if(!Sem.PlotActive)
	{
		if(0==LCDHoldoffCounter)
		{
			LCDHoldoffCounter = 4;
			for(x=0; x<122; x++)
				PlotBuf[x] = (16 + (pBuf[x]>>11) );
	    	PutTxQ(0x82);	    //清屏
			SetLcdPos(0,0);		//设定坐标点
			WriteCStr(TIME_STR);
			PlotPos = 0;		    //x 位置
			PixelSendState = 0;
			Sem.PlotActive = 1;	//使能LCD写状态机
		}
	}
}

//画幅值对数值和采样频率对应关系的子程序
void PlotFreq( int* pBuf )
{
	if(!Sem.PlotActive)
	{
		if(0==LCDHoldoffCounter)
		{
			LCDHoldoffCounter = 4;
			CalcFFT( (fractional*)pBuf, PlotBuf);	//变换log2 mag 对应的 freq
	    		PutTxQ(0x82);	//清屏
			SetLcdPos(0,0);		//设定坐标点
			WriteCStr(FREQ_STR);
			PlotPos = 0;		    //x位置
			PixelSendState = 0;
			Sem.PlotActive = 1;	//使能LCD写状态机
		}
	}
}

//LCD画点子程序
void ServiceLCD( )
{
    if( (TxQTail == TxQHead ) && Sem.PlotActive ) 	//如果还有点要画且SPI空闲
	{											
		PixelSendState++;
		if( PixelSendState==1 )
		{
	    	PutTxQ(0xD8);			//画点开关打开
		}
		else if( PixelSendState==2 )
		{
	    	PutTxQ(PlotPos );		    //x点
		}
		else
		{
	    	PutTxQ( (unsigned char)PlotBuf[PlotPos++] );
			PixelSendState = 0;			// y点
		}
		if(PixelSendState>=3)
			PixelSendState = 0;
		if(PlotPos>=122)
	    	Sem.PlotActive = 0;	//画点结束
	}
}

⌨️ 快捷键说明

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