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

📄 main.cpp

📁 USB中文数据说明
💻 CPP
📖 第 1 页 / 共 3 页
字号:


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 + -