- //=================================================================================================
- // CPU 用 HIRC/6 = 2MHz 工作, RTC 一秒钟唤醒 CPU 一次, PA3 接 KEY 也会唤醒 CPU
- // UART 2400接收10字节唤醒 CPU, 不到 10 字节, 255位无后续数据也会唤醒 CPU
- // 进入主循环之前,对GP22写入7个配置字, 并写入ID, 每秒读取 ID 显示在 LCD 上
- // Copyright (C) 2015 Nuvoton(SH) Technology Corp. All rights reserved
- //=================================================================================================
- #include "Nano1X2Series.h"
- #include "IP_Init.h"
- // GP22 的七个配置寄存器的值 ////////////////////////////////////////////////////////////
- uint8_t const GP22_reg0[] = {0x80, 0x83, 0x0B, 0x68, 0x0E};
- uint8_t const GP22_reg1[] = {0x81, 0x21, 0x44, 0xC0, 0x0d}; // 第一个字节是 opcode
- uint8_t const GP22_reg2[] = {0x82, 0xA0, 0x1E, 0x00, 0x0d};
- uint8_t const GP22_reg3[] = {0x83, 0xF0, 0x92, 0x07, 0x0c}; // 最后一个字节是 ID
- uint8_t const GP22_reg4[] = {0x84, 0x20, 0x00, 0x20, 0x01};
- uint8_t const GP22_reg5[] = {0x85, 0x50, 0x00, 0x00, 0x06};
- uint8_t const GP22_reg6[] = {0x86, 0xC0, 0xC0, 0x60, 0x08};
- uint8_t Str_Tx[] = {0xB7,0,0,0, 0,0,0,0} ; // 第一个字节是 opcode
- uint8_t SPI_Rx[64] = " \nUART0 is OK now !" ; // 接收缓存
- uint8_t COM0_Rx[64] ; // 接收缓存
- uint8_t COM1_Rx[64] ; // 接收缓存
- /// PA~PE都是16个GPIO, 没引出的脚也要配成输入并打开弱上拉 ///////////////////////////////
- void GpioInit(void)
- {
- // PA 11GPIO, PA0~6,12~15
- // PA0高接通V30, PA1,5_EPROM, PA2_EPROM_VCC, PA4_VCC_30, 这几个输出0
- // PA12~PA14, PA15_GPIO接SPISS, PA3_KEY, PA6空
- PA->DOUT = 0xFFC8 ;
- PA->PMD = 0x40000595 ; // PA3 OD 输出1
- PA->PUEN = 0x2FC8 ; // 1使能弱上拉
- SYS->PA_H_MFP = SYS_PA_H_MFP_PA14_MFP_SPI1_SCLK
- | SYS_PA_H_MFP_PA13_MFP_SPI1_MISO0
- | SYS_PA_H_MFP_PA12_MFP_SPI1_MOSI0 ;
- SYS->PA_L_MFP = 0 ;
-
- // PB 11个GPIO, PB0~3,6,10~15
- // PB0,1空, PB2_GP22复位输出1, PB3_INT入,PB6_Tx, PB10_Rx,PB11~12空,PB15_LCD
- PB->DOUT = 0xFFFF ;
- PB->PMD = 0 ;
- PB->PUEN = 0x3A0F ;
- PB->OFFD = 0x80000000 ; // PB15 关数字输入
- SYS->PB_L_MFP = SYS_PB_L_MFP_PB6_MFP_UART1_TX ;
- SYS->PB_H_MFP = SYS_PB_H_MFP_PB15_MFP_LCD_S19
- | SYS_PB_H_MFP_PB14_MFP_UART0_TX
- | SYS_PB_H_MFP_PB13_MFP_UART0_RX
- | SYS_PB_H_MFP_PB10_MFP_UART1_RX ;
-
- // PC无10~13, 有12个GPIO,全是LCD接口
- PC->DOUT = 0xFFFF ;
- PC->PMD = 0 ;
- PC->PUEN = 0xFFFF ;
- PC->OFFD = 0xFFFF0000;
- SYS->PC_L_MFP = 0x88888888; // seg11 ~ 18
- SYS->PC_H_MFP = 0x88888888; // seg7 ~ 8
-
- // PD 有16个GPIO, PD11/12是GPIO,其它全是LCD接口
- PD->DOUT = 0xE7FF ;
- PD->PMD = 0 ;
- PD->PUEN = 0xE7FF ;
- PD->OFFD = 0xE7FF0000;
- SYS->PD_L_MFP = 0x88888888; // seg6 ~ 0, COM3
- SYS->PD_H_MFP = 0x88800888 | SYS_PD_H_MFP_PD12_MFP_CLK_Hz; // COM2 ~ 0, V3 ~ 1
-
- // 64PIN 封装 PE 没引出, 也要配成输入打开弱上拉 ///////////////////////////////////////
- PE->DOUT = 0xFFFF ;
- PE->PMD = 0 ;
- PE->PUEN = 0xFFFF ;
- SYS->PE_L_MFP = 0 ;
- SYS->PE_H_MFP = 0 ;
-
- // PF012345. 有6个GPIO
- PF->DOUT = 0xFFFF ;
- PF->PMD = 0 ;
- PF->PUEN = 0xFFFC ; // PF01/02 关弱上拉
- PF->OFFD = 0x00030000 ; // PF01/02 关数字输入
- SYS->PF_L_MFP = SYS_PF_L_MFP_PF1_MFP_X32_OUT
- | SYS_PF_L_MFP_PF0_MFP_X32_IN ;
-
- PA->ISRC = ~0 ; // 清标志
- PA->IMD = 0 ; // 边沿中断
- PA->IER = 0x00080008 ; // 上下沿中断
- PA->DBEN = 0x00000008 ; // 使能去抖
-
- GPIO->DBNCECON = 0x002F ; // HCLK 消抖 约 2.7 ms
- NVIC_SetPriority(GPABC_IRQn, 2);
- // NVIC->ISER[0] = 1<<GPABC_IRQn ;
- }
- //// SPI1 少量数据收发, 不用中断, 代码简单 //////////////////////////////////////////////
- // 输入: pTr, 待发送的字符
- // Num, 全双工收发送字符个数
- // pRx, 接收字符存放地址
- void SPI1_TxRx(uint8_t *pTx, uint32_t Num, uint8_t *pRx )
- {
- uint32_t Cnt = 6, CntRx = Num ;
-
- PA->DOUT &= ~0x8000 ; // SS = 0 ;
- while(Num){ --Num ;
- SPI1->TX1 = *pTx++ ;
- if(--Cnt == 0) break ;
- }
-
- while(CntRx){ --CntRx;
- while(SPI1->STATUS & SPI_STATUS_RX_EMPTY_Msk) ;
- *pRx++ = SPI1->RX1 ;
- if(Num){ --Num; SPI1->TX1 = *pTx++; }
- }
- PA->DOUT |= 0x8000 ; // SS = 1 ;
- }
- /////////////////////////////////////////////////////////////////////////////////////////
- int32_t main(void)
- {
- uint8_t *pStr ;
-
- SysClkInit() ;
- Timer1Init() ; // Delayus()延时用 Timer1
- RTC_Init();
- LCD_Init() ;
- SPI1_Init(3) ; // SPI1 时钟是 HCLK 的3分频
- PB->PMD |= 0x10 ; // PB2控制GP22复位, 低有效
- // 与GPIO输出有关的外设配置放此
- UART0_Init() ;
- UART1_Init() ;
- GpioInit() ; // 配置GPIO
-
- UART0->THR = '\n' ; UART0->THR = 'O' ; UART0->THR = 'K' ;
- UART1->THR = '\n' ; UART1->THR = 'O' ; UART1->THR = 'K' ;
-
- //// 写 GP22 的七个配置寄存器 /////////////////////////////////////////////////////////
- SPI1_TxRx((uint8_t*)GP22_reg0, 5, SPI_Rx) ;
- SPI1_TxRx((uint8_t*)GP22_reg1, 5, SPI_Rx) ;
- SPI1_TxRx((uint8_t*)GP22_reg2, 5, SPI_Rx) ;
- SPI1_TxRx((uint8_t*)GP22_reg3, 5, SPI_Rx) ;
- SPI1_TxRx((uint8_t*)GP22_reg4, 5, SPI_Rx) ;
- SPI1_TxRx((uint8_t*)GP22_reg5, 5, SPI_Rx) ;
- SPI1_TxRx((uint8_t*)GP22_reg6, 5, SPI_Rx) ;
-
- Delayus(50000) ; // 等 UART 发送结束
-
- COM0_Data.NumRx = 0 ; COM0_Data.pRx = COM0_Rx ; COM0_Data.NumRx = 60 ;
- COM1_Data.NumRx = 0 ; COM1_Data.pRx = COM1_Rx ; COM1_Data.NumRx = 60 ;
-
- Event = 0 ; pStr = 0 ;
- while(1){
- if((UART0->FSR & UART_FSR_RX_EMPTY_F_Msk) == 0) Event |= Event_UART0_Rx ;
- if((UART1->FSR & UART_FSR_RX_EMPTY_F_Msk) == 0) Event |= Event_UART1_Rx ;
- while(Event == 0){ // 无事可做, 休眠
- SYS_UnlockReg() ;
- CLK->PWRCTL |= CLK_PWRCTL_PWRDOWN_EN ; // 休眠功能使能位,自动清零
- SCB->SCR |= 0x04 ; // 掉电模式
- SYS_LockReg() ;
- __wfi() ; // 进入休眠状态
- }
- //// 任务 1, 优先级最高, 越靠后, 优先级最低 /////////////////////////////////////////
- if(Event & Event_RTC_INT){ Event &= ~Event_RTC_INT ;
- SPI1_TxRx((uint8_t*)Str_Tx, 8, SPI_Rx) ; // 读出GP22的7个ID,显示在LCD上
- LCD->MEM_0 = TabLCD[SPI_Rx[1]] ; LCD->MEM_0 += TabLCD[SPI_Rx[2]] << 16 ;
- LCD->MEM_1 = TabLCD[SPI_Rx[3]] ; LCD->MEM_1 += TabLCD[SPI_Rx[4]] << 16 ;
- LCD->MEM_2 = TabLCD[SPI_Rx[5]] ; LCD->MEM_2 += TabLCD[SPI_Rx[6]] << 16 ;
- LCD->MEM_3 = TabLCD[SPI_Rx[7]] ; LCD->MEM_3 += TabLCD[8] << 16 ;
- }
- //// 任务 2 /////////////////////////////////////////////////////////////////////////
- else if(Event & Event_KEY_PUSH){
- PE->DOUT ^= 0x40 ;
-
- Event &= ~Event_KEY_PUSH ; // 才再次处理按键
- }
- //// 任务 3 /////////////////////////////////////////////////////////////////////////
- else if(Event & Event_UART0_Rx){
- UART0->CTL |= UART_CTL_WAKE_THRESH_EN_Msk ; // 再次使能唤醒
- if(pStr == 0) pStr = COM0_Rx ; // 接收数据的开头
-
- // 处理数据 /////////////////////////////////////////////////////////////
- if(pStr != COM0_Data.pRx){
- if((UART0->FSR & UART_FSR_TX_FULL_F_Msk) == 0)
- UART0->THR = *pStr++ ;
- }
- /////////////////////////////////////////////////////////////////////////
-
- if(((TIMER1->DR - Uart0_Tick)&0xFFFFFF) > 70000){ // 70ms 无后续数据
- pStr = 0 ;
- COM0_Data.NumRx = 0 ; // 接收的数据丢掉
- COM0_Data.pRx = COM0_Rx ;
- COM0_Data.NumRx = 60 ; // 重新开始接收最多60字节
- Event &= ~Event_UART0_Rx ; // 可以休眠了
- }
- }
- //// 任务 4 /////////////////////////////////////////////////////////////////////////
- else
- if(Event & Event_UART1_Rx){ Event &= ~Event_UART1_Rx ;
-
- UART1->CTL |= UART_CTL_WAKE_THRESH_EN_Msk ; // 再次使能唤醒
- pStr = COM1_Rx ;
- while(pStr != COM1_Data.pRx){
- while(UART1->FSR & UART_FSR_TX_FULL_F_Msk) ;
- UART1->THR = *pStr++ ;
- Delayus(70) ;
- }
- while((UART1->FSR & UART_FSR_TE_F_Msk) == 0) ; // 等发送结束
- COM1_Data.pRx = COM1_Rx ; COM1_Data.NumRx = 30 ; // 重新启动接收
- }
- /////////////////////////////////////////////////////////////////////////////////////
- else Event = 0 ;
- }
- }