📄 lcd.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 + -