📄 main.cpp
字号:
SystemObj::SystemObj(void)
{
volatile unsigned int start;
Disable_IRQ();//关中断
PINSEL->PIN_SEL0 = 0x00000000; // 设置管脚连接GPIO
PINSEL->PIN_SEL1 = 0x00000000; // 设置管脚连接GPIO
PINSEL->PIN_SEL2 = 0x00000000; // 设置管脚连接GPIO
PINSEL->PIN_SEL1 |= (P0_16_EINT0 << P0_16_PINSEL);// P0.16连接到EINT0
PINSEL->PIN_SEL1 |= (P0_30_EINT3 << P0_30_PINSEL);// P0.30连接到EINT3
P0->IODIR = 0x00000000; // 设置P0口为输入
P1->IODIR = 0x00000000; // 设置P1口为输入
VIC->IntEnClr = 0xffffffff; // 清除所有中断使能
VIC->SoftIntClr = 0xffffffff;//清除所有软中断标志
VIC->IntSelect = 0;//全部中断为IRQ中断或默认中断
for(int i = 0; i <= 15; i ++) {
VIC->VectAddrs[i] = i;//刷新向量地址寄存器VICVectAddr0~VICVectAddr15
}
for (start = 1; start < 10000; start ++);
SystemInit();
}
void SystemObj::SystemInit(void)
{
if (SystemRamTest != 0x55aa) {
SystemRamTest = 0x55aa;
}
WdtInit();
Timer0Init();
LedInit();
BeepInit();
VicIntSetup();
}
LedObj::LedObj(void)
{
LedInit();
}
void LedObj::LedInit(void)
{
P0->IODIR |= (1 << RCLK);
P0->IOCLR = (1 << RCLK);
POWER->P_CONP |= (1 << PCSPI0);
PINSEL->PIN_SEL0 |= ((P0_4_SCK0 << P0_4_PINSEL) | (P0_6_MOSI0 << P0_6_PINSEL));
SPI->SPI_SPCCR = 0x52; // 设置SPI时钟分频
SPI->SPI_SPCR =
(1 << CPHA) | // CPHA = 0, 数据在SCK 的第一个时钟沿采样
(1 << CPOL) | // CPOL = 1, SCK 为低有效
(1 << MSTR) | // MSTR = 1, SPI 处于主模式
(0 << LSBF) | // LSBF = 0, SPI 数据传输MSB (位7)在先
(0 << SPIE); // SPIE = 0, SPI 中断被禁止
}
void LedObj::LedDisplay(unsigned char cData)
{
SPI->SPI_SPDR = LedTab[cData]; //发送数据(相当于51的SBUF = DATA)
while(!(SPI->SPI_SPSR & (1 << SPIF))); // 等待SPIF置位,即等待数据发送完毕
P0->IOCLR = (1 << RCLK);
__nop();
__nop();
__nop();
P0->IOSET = (1 << RCLK);
}
LcdObj::LcdObj(void)
{
LcdSpiInit();//SPI初始化
}
void LcdObj::LcdSpiInit(void)
{
/* 设置MOSI 和SCK 及SS 为输出,其他为输入 */
P0->IODIR |= (1 << SSEL1);
P0->IOCLR = (1 << SSEL1);
POWER->P_CONP |= (1 << PCSPI1);
PINSEL->PIN_SEL1 |= ((P0_17_SCK1 << P0_17_PINSEL) | (P0_18_MISO1 << P0_18_PINSEL) | (P0_19_MOSI1 << P0_19_PINSEL));
SSP->SSP_CR0 = (0x01 << 8) | // SCR 设置SPI时钟分频
(0x00 << 7) | // CPHA 时钟输出相位,仅SPI模式有效
(0x00 << 6) | // CPOL 时钟输出极性,仅SPI模式有效 0
(0x00 << 4) | // FRF 帧格式 00=SPI,01=SSI,10=Microwire,11=保留
(0x07 << 0); // DSS 数据长度,0000-0010=保留,0011=4位,0111=8位,1111=16位
SSP->SSP_CR1 = (0x00 << 3) | // SOD 从机输出禁能,1=禁止,0=允许
(0x00 << 2) | // MS 主从选择,0=主机,1=从机
(0x01 << 1) | // SSE SSP使能,1=允许SSP与其它设备通信
(0x00 << 0); // LBM 回写模式
SSP->SSP_CPSR = 0x52; // PCLK分频值
// SSP->SSP_IMSC = 0x07; // 中断屏蔽寄存器
SSP->SSP_ICR = 0x03; // 中断清除寄存器
}
//__inline
void LcdObj::LcdInit(void)
{
/*---------------------------------------------------
LCD模块上电等待延时
----------------------------------------------------*/
LcdClearBuffer();
LcdSendCommand(0x20);//发送4位控制命令
// LcdSendCommand(0x30);//发送8位控制命令//与8位4位无关!!!
LcdSendCommand(0x02);//发送位址归位命令,设定DDRAM位址计数器为0
LcdSendCommand(0x04);//发送进入点命令
LcdSendCommand(0x0c);//发送开显示关光标命令
LcdSendCommand(0x01);//发送清除显示命令
LcdSendCommand(0x80);//发送设定DDRAM地址0x00命令
SetLcdDisplayPos(0, 0);//汉字定位到上行左端
LcdDisplay("12345678汉字定位");
SetLcdDisplayPos(1, 0);//汉字定位到上行左端
LcdDisplay("8765432187654321");
SetLcdDisplayPos(2, 0);//汉字定位到上行左端
LcdDisplay("1234657812345678");
SetLcdDisplayPos(3, 0);//汉字定位到上行左端
LcdDisplay("1234567812345678");
}
//__inline
void LcdObj::LcdSend(char cData)
{
SSP->SSP_DR = cData;
// while( (SSP->SSP_SR & (1 << TFE)) == 0 ); // 等待TFE置位,即发送FIFO空
while(SSP->SSP_SR & (1 << BSY)); // 等待TFE置位,即发送FIFO空
// return SSP->SSP_DR;
}
/*--------------------------------------------------------
发送8位LCD控制命令
--------------------------------------------------------*/
//__inline
void LcdObj::LcdSendCommand(char cCommand)
{
/*--------------------------------------------------------
发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右)
--------------------------------------------------------*/
P0->IOSET = (1 << SSEL1);//SS=1,启动SPI
LcdSend(0xf8);//发送LCD控制命令
LcdSend(cCommand & 0xf0);//发送高4位LCD控制命令
LcdSend(cCommand << 4);//发送低4位LCD控制命令
P0->IOCLR = (1 << SSEL1);//SS=0,关闭SPI
if (cCommand == 0x01) _delay_loop_(160);//1.6mS
else _delay_loop_(72);//st7920要求等待72uS
}
/*--------------------------------------------------------
发送8位LCD显示数据
--------------------------------------------------------*/
//__inline
void LcdObj::LcdSendData(char cData)
{
/*--------------------------------------------------------
发送同步脉冲11111 WR(0) RS(0) 0发送顺序从左至右)
--------------------------------------------------------*/
P0->IOSET = (1 << SSEL1);//SS=1,启动SPI
LcdSend(0xfa);//发送LCD显示数据
LcdSend(cData & 0xf0);//发送高4位LCD显示数据
LcdSend(cData << 4);//发送低4位LCD显示数据
P0->IOCLR = (1 << SSEL1);//SS=0,关闭SPI
_delay_loop_(72);//st7920要求等待延时72uS
}
//__inline
void LcdObj::SetLcdDisplayPos(unsigned char row, unsigned char col)
{
row &= 0x03;//4行汉字
col &= 0x0f;//每行8个汉字16个字符
LcdRow = row;
LcdCol = col;
LcdRowWriteEnable[row] = 1;//允许此行刷新汉字显示
}
//__inline
void LcdObj::LcdClearBuffer(void)
{
unsigned char i, j;
for (i = 0;i < 4;i ++) {
for (j = 0;j < 16; j ++) {
LcdBuffer[i][j] = ' ';
}
LcdRowWriteEnable[i] = 1;//允许此行刷新汉字显示
}
LcdRow = 0;
LcdCol = 0;
}
//__inline
void LcdObj::LcdDisplayBuffer(void)
{
unsigned char i, j;
for (i = 0; i < 4; i ++) {//4行汉字
if (LcdRowWriteEnable[i]) {//允许此行刷新汉字显示
LcdSendCommand(0x80 + (i & 1) * 16 + (i >> 1) * 8);//移动光标
for (j = 0; j < 16; j ++) {//每行8个汉字16个字符
LcdSendData(LcdBuffer[i][j]);//刷新显示字符
}
LcdRowWriteEnable[i] = 0;//过后不允许此行刷新汉字显示
}
}
}
//__inline
void LcdObj::LcdDisplay(const char * string)
{
while(*string) {
LcdBuffer[LcdRow][LcdCol ++] = *string ++;
}
}
RtcObj::RtcObj(void){
RtcInit();//SPI初始化
}
void RtcObj::RtcInit(void){
POWER->P_CONP |= (1 << PCRTC);
RTC->RTC_CCR = 0;
RTC->RTC_CIIR = (1 << IMSEC); // 设置秒值的增量产生一次中断
RTC->RTC_ILR = (1 << RTCALF) | (1 << RTCCIF); // 清除RTC增量和报警中断标志
RTC->RTC_CCR = (1 << CLKEN) | (1 << CLKSRC); // 启动RTC
if (SystemRamTest != 0x55aa55aa) {//RAM真正掉电后才清除时钟!!!
/*
RTC->RTC_YEAR = 2006;
RTC->RTC_MONTH = 3;
RTC->RTC_DOM = 30;
RTC->RTC_HOUR =8;
RTC->RTC_MIN =53;
RTC->RTC_SEC = 0;
RTC->RTC_DOW = 4;
*/
}
}
/*----------------------------------------------------------------------------------------
0000年~9999年星期算法
-----------------------------------------------------------------------------------------*/
unsigned int RtcObj::GetDow(unsigned int y, unsigned int m, unsigned int d)
{
unsigned int w, c;
if (m <= 2){
m |= 4;//1月2月同5月六月表
y--;
}
c = y / 100;
c &= 0x03;//百年%4
y %= 100;
w = ((c | (c << 2)) + (y + (y >> 2)) + (13 * m + 8)/ 5 + d) % 7;//(星期=百年%4*5+年+年/4+(13*月+8)/5+日)%7
return w;//返回星期
}
/*----------------------------------------------------------------------------------------
0000年~9999年月最大天数算法
-----------------------------------------------------------------------------------------*/
unsigned int RtcObj::GetDom(unsigned int y, unsigned int m)
{
unsigned int dn;
dn = GetDow(y, m + 1, 1) - GetDow(y, m, 1);//m+1=13表示明年的1月
if (dn >= 0x80) dn += 7;
return dn + 28;//返回当月的最大天数
}
//inline
UartObj::UartObj(void)
{
UartInit();
}
//inline
void UartObj::UartInit(void)
{
unsigned int Fdiv;
PINSEL->PIN_SEL0 |= (P0_0_TXD0 << P0_0_PINSEL) | (P0_1_RXD0 << P0_1_PINSEL); //设置I/O连接到UART0
U0->LCR = 0x83; // DLAB=1,允许设置波特率
Fdiv = (Fpclk / 16) / UART_BPS; // 设置波特率
U0->DLM = Fdiv / 256;
U0->DLL = Fdiv % 256;
U0->LCR = 0x03;
U0->FCR = 0xc7; /* 初始化FIFO 接收14个字节就中断*/
U0->IER = 0x07; /* 允许接收发送中断 */
RxCount = TxCount = 0;
RxdCount = TxdCount = 0;
for (int i = 0; i < 128; i ++) {
RxBuffer[i] = TxBuffer[i] = 0;
}
}
void UartObj::Exec(void)
{
static unsigned char cData = 0;
unsigned char ch;
Status = U0->IIR & 0x0f;
switch (Status) {
case 0x06://接收线状态
switch (U0->LSR) {
case 0x63:
break;
}
break;
case 0x04://接收数据可用
case 0x0c://字符超时指示
do{
ch = U0->RBR;
if (ch == '$') {
cData = '$';
RxBuffer[RxCount ++] = ch;
}
else if(cData == '$'){
if (ch >= 0x20) {
RxBuffer[RxCount ++] = ch;
}
else if (ch == 0x0d) {
RxBuffer[RxCount ++] = ch;
}
else if (ch == 0x0a) {
// if (RxBuffer[(RxCount - 1) & 0x7f] == 0x0d) {
cData = 0;
RxBuffer[RxCount ++] = ch;
//isr_evt_set (DefBeep_1, Beep_Task);
isr_evt_set (1, Uart_Task);
// }
}
}
}while(U0->LSR & (1 << RDR));
break;
case 0x02://THRE中断
break;
}
}
/*
RTC->RTC_YEAR = 2006;
RTC->RTC_MONTH = 3;
RTC->RTC_DOM = 30;
RTC->RTC_HOUR =8;
RTC->RTC_MIN =53;
RTC->RTC_SEC = 0;
RTC->RTC_DOW = 4;
*/
void UartObj::LoadDataBuff(void)
{
unsigned char ch;
unsigned int val;
if (RxBuffer[RxdCount ++] == '$') {
ch = RxBuffer[RxdCount ++];//取PC命令
switch(ch) {
case 'D'://$DS2006-03-18*CRC<CR>
ch = RxBuffer[RxdCount ++];//取PC命令
switch(ch) {
case 'S'://系统日期
if (RxBuffer[RxdCount + 10] == 0x0a) {
RTC->RTC_CCR = 0;
val = 0;
for (int i = 0; i < 4; i ++) {
ch = RxBuffer[RxdCount ++];
val = val * 10 + (ch - '0');
}
RTC->RTC_YEAR = val;
RxdCount ++;//放弃'-'
val = 0;
for (int i = 0; i < 2; i ++) {
ch = RxBuffer[RxdCount ++];
val = val * 10 + (ch - '0');
}
RTC->RTC_MONTH = val;
RxdCount ++;//放弃'-'
val = 0;
for (int i = 0; i < 2; i ++) {
ch = RxBuffer[RxdCount ++];
val = val * 10 + (ch - '0');
}
RTC->RTC_DOM = val;
/*
RxdCount ++;//放弃'-'
val = 0;
for (int i = 0; i < 1; i ++) {
RxdCount &= 0x7f;
ch = RxBuffer[RxdCount ++];
val = val * 10 + (ch - '0');
}
*/
val = Rtc_.GetDow(RTC->RTC_YEAR, RTC->RTC_MONTH, RTC->RTC_DOM);
RTC->RTC_DOW = val;
// RxdCount ++;//放弃0x0d
RxdCount ++;//放弃0x0a
RTC->RTC_CCR = (1 << CLKEN) | (1 << CLKSRC); // 启动RTC
os_evt_set (2888, Lcd_Task);//开关BEEP
os_evt_set (DefBeep_1, Beep_Task);//开关BEEP
}
else {
RxdCount = RxCount;//失败,取下次首指针
}
break;
}
break;
case 'T'://$TS00:01:08*CRC<CR>
ch = RxBuffer[RxdCount ++];//取PC命令
switch(ch) {
case 'S'://系统时间
if (RxBuffer[RxdCount + 8] == 0x0a) {
RTC->RTC_CCR = 0;
ch = RxBuffer[RxdCount ++];
val = (ch - '0') * 10;
ch = RxBuffer[RxdCount ++];
val += ch - '0';
RTC->RTC_HOUR = val;
RxdCount ++;//放弃':'
ch = RxBuffer[RxdCount ++];
val = (ch - '0') * 10;
ch = RxBuffer[RxdCount ++];
val += ch - '0';
RTC->RTC_MIN = val;
RxdCount ++;//放弃':'
ch = RxBuffer[RxdCount ++];
val = (ch - '0') * 10;
ch = RxBuffer[RxdCount ++];
val += ch - '0';
RTC->RTC_SEC = val;
// RxdCount ++;//放弃0x0d
RxdCount ++;//放弃0x0a
RTC->RTC_CCR = (1 << CLKEN) | (1 << CLKSRC); // 启动RTC
os_evt_set (1888, Lcd_Task);//开关BEEP
os_evt_set (DefBeep_1, Beep_Task);//开关BEEP
}
else {
RxdCount = RxCount;//失败,取下次首指针
}
break;
}
break;
}
}
else {
RxdCount = RxCount;//失败,取下次首指针
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -