*(volatile unsigned short int *)(0x60020000)=val; 的解析

内存地址赋值操作解析
博客介绍了代码“*(volatile unsigned short int *)(0x60020000)=val;”的含义。先将0x60020000这个数字强制转换为地址指针类型,使其指向某块内存位置,然后把val赋值存储到该地址指向的内存单元中。

*(volatile unsigned short int *)(0x60020000)=val;

0x60020000 地址值,你想象成内存地址好了,这是一串数字
(volatile unsigned short int )(0x60020000) 将数字强制转换为地址指针类型,也就是经过这样一转换, 0x60020000 就指向某一块内存位置了,第二个就简单了,就是把val 赋值存储到0x60020000 指向的内存单元中。

#ifndef LS1C102_H_ #define LS1C102_H_ #include <stdint.h> #include "bsp.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #define bit(x) (1<<x) #define SECTION(x) __attribute__((section(x))) // 指定段位置 #ifdef __cplusplus #define __I volatile /*!< defines 'read only' permissions */ #else #define __I volatile const /*!< defines 'read only' permissions */ #endif #define __O volatile /*!< defines 'write only' permissions */ #define __IO volatile /*!< defines 'read / write' permissions */ typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState; typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; //------------------------------------------------------------------------------------------------- // 寄存器 Read/Write 操作 //------------------------------------------------------------------------------------------------- /* • 8 Bits */ #define READ_REG8(Addr) (*(volatile unsigned char*)(Addr)) #define WRITE_REG8(Addr, Val) (*(volatile unsigned char*)(Addr) = (Val)) #define OR_REG8(Addr, Val) (*(volatile unsigned char*)(Addr) |= (Val)) #define AND_REG8(Addr, Val) (*(volatile unsigned char*)(Addr) &= (Val)) /* • 16 Bits */ #define READ_REG16(Addr) (*(volatile unsigned short*)(Addr)) #define WRITE_REG16(Addr, Val) (*(volatile unsigned short*)(Addr) = (Val)) #define OR_REG16(Addr, Val) (*(volatile unsigned short*)(Addr) |= (Val)) #define AND_REG16(Addr, Val) (*(volatile unsigned short*)(Addr) &= (Val)) /* • 32 Bits */ #define READ_REG32(Addr) (*(volatile unsigned int*)(Addr)) #define WRITE_REG32(Addr, Val) (*(volatile unsigned int*)(Addr) = (Val)) #define OR_REG32(Addr, Val) (*(volatile unsigned int*)(Addr) |= (Val)) #define AND_REG32(Addr, Val) (*(volatile unsigned int*)(Addr) &= (Val)) #define SET_BIT(REG, BIT) ((REG) |= (BIT)) #define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) #define READ_BIT(REG, BIT) ((REG) & (BIT)) #define CLEAR_REG(REG) ((REG) = (0x0)) #define WRITE_REG(REG, VAL) ((REG) = (VAL)) #define READ_REG(REG) ((REG)) #define MODIFY_REG(REG, CLEARMASK, SETMASK) WRITE_REG((REG), (((READ_REG(REG)) & (~(CLEARMASK))) | (SETMASK))) / NORMAL ADDRESS SPACE / #define UNCACHED_MEMORY_ADDR 0xa0000000 #define UNCACHED_TO_PHYS(x) ((x) & 0x1fffffff) #define PHYS_TO_UNCACHED(x) ((x) | UNCACHED_MEMORY_ADDR) #define RAM0_BASE PHYS_TO_UNCACHED(0x00000000) //iram #define RAM1_BASE PHYS_TO_UNCACHED(0x00001000) //dram #define SPI_MEM_BASE PHYS_TO_UNCACHED(0x1e000000) //spi_flash #define FLASH_MEM_BASE PHYS_TO_UNCACHED(0x1f000000) //on-chip flash #define FLASH_BASE PHYS_TO_UNCACHED(0x1fe60000) //flash regs #define SPI_BASE PHYS_TO_UNCACHED(0x1fe70000) //spi regs #define UART0_BASEADDR PHYS_TO_UNCACHED(0x1fe80000) //uart0 #define UART1_BASEADDR PHYS_TO_UNCACHED(0x1fe88000) //uart1 #define UART2_BASEADDR PHYS_TO_UNCACHED(0x1fe8c000) //uart2 #define I2C_BASE PHYS_TO_UNCACHED(0x1fe90000) //i2c #define INTC_BASE PHYS_TO_UNCACHED(0x1fea0000) //Interrupt_Regs_Baseadd #define PMU_BASE PHYS_TO_UNCACHED(0x1feb0000) //PMU // 0xbfeb0000 #define TSENSOR_BASE PHYS_TO_UNCACHED(0x1feb4000) //tsensor #define RTC_BASE PHYS_TO_UNCACHED(0x1feb8000) //rtc #define DMA_BASE PHYS_TO_UNCACHED(0x1fec0000) //DMA #define VPWM_BASE PHYS_TO_UNCACHED(0x1fec0020) //vpwm #define TIMER_BASE PHYS_TO_UNCACHED(0x1fed0000) //timer #define ATE_Freq (*(volatile int *)0xbf0201b0) //------------------------------------------------------------------------------------------------- // 地址空间分布 //------------------------------------------------------------------------------------------------- #define LS1C102_IRAM_ADDR 0x80000000 // - 只能用于取址 #define LS1C102_IRAM_SIZE 0x1000 // - IRAM 大小 = 4K #define LS1C102_DRAM_ADDR 0x80001000 // - 只能用于取指 #define LS1C102_DRAM_SIZE 0x1000 // - IRAM 大小 = 4K #define LS1C102_SPIFLASH_ADDR 0xBE000000 // SPI Flash 存储区 #define LS1C102_FLASH_ADDR 0xBF000000 // On-chip Flash 存储区 #define LS1C102_BOOT_ADDR 0x1C000000 // Boot from SPI Flash or On-chip Flash #define LS1C102_FLASH_BASE 0xBFE60000 // Flash 控制寄存器基地址 #define LS1C102_SPI_BASE 0xBFE70000 // SPI 控制寄存器基地址 #define LS1C102_UART0_BASE 0xBFE80000 // UART0 基地址 #define LS1C102_UART1_BASE 0xBFE88000 // UART1 基地址 #define LS1C102_UART2_BASE 0xBFE8C000 // UART2 基地址 #define LS1C102_I2C_BASE 0xBFE90000 // I2C 基地址 #define LS1C102_INTC_BASE 0xBFEA0000 // 中断控制寄存器基地址 #define LS1C102_PMU_BASE 0xBFEB0000 // 电源管理单元寄存器基地址 #define LS1C102_TSENSOR_BASE 0xBFEB4000 // 触摸传感器寄存器基地址 #define LS1C102_RTC_BASE 0xBFEB8000 // 实时时钟寄存器基地址 #define LS1C102_DMA_BASE 0xBFEC0000 // DMA 寄存器基地址 #define LS1C102_VPWM_BASE 0xBFEC0020 // VPWM 寄存器基地址 #define LS1C102_TIMER_BASE 0xBFED0000 // 定时器寄存器基地址 //------------------------------------------------------------------------------------------------- // 电源管理单元 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned int ChipCtrl; // 0x00 全局配置 volatile unsigned int CmdSts; // 0x04 命令与状态 volatile unsigned int Count; // 0x08 时间计数器 volatile unsigned int Compare; // 0x0c 唤醒时间配置 volatile unsigned int IOSEL0; // 0x10 IO复用选择 0 volatile unsigned int IOSEL1; // 0x14 IO复用选择 1 volatile unsigned int IOSEL2; // 0x18 IO复用选择 2 volatile unsigned int IOSEL3; // 0x1c IO复用选择 3 volatile unsigned int ExIntEn; // 0x20 外部中断使能 volatile unsigned int ExIntPol; // 0x24 外部中断极性 volatile unsigned int ExIntEdge; // 0x28 外部中断边沿 volatile unsigned int ExIntSrc; // 0x2c 外部中断状态 volatile unsigned int WdtCfg; // 0x30 看门狗配置 volatile unsigned int WdtFeed; // 0x34 喂狗 volatile unsigned int PowerCfg; // 0x38 电源配置 volatile unsigned int CommandW; // 0x3C XXX datasheet上没有描述这个寄存器, == CmdSts? volatile unsigned int GPIOA_OE; // 0x40 GPIOA 输出使能 volatile unsigned int GPIOA_O; // 0x44 GPIOA 输出 volatile unsigned int GPIOA_I; // 0x48 GPIOA 输入 volatile unsigned int rsv1; // 0x4C volatile unsigned int GPIOB_OE; // 0x50 GPIOB 输出使能 volatile unsigned int GPIOB_O; // 0x54 GPIOB 输出 volatile unsigned int GPIOB_I; // 0x58 GPIOB 输入 volatile unsigned int rsv2; // 0x5C volatile unsigned int Pulse0; // 0x60 脉冲输出配置 0 volatile unsigned int Pulse1; // 0x64 脉冲输出配置 1 volatile unsigned int UserDat; // 0x68 用户数据 volatile unsigned int AdcCtrl; // 0x6c ADC 控制 volatile unsigned int AdcDat; // 0x70 ADC 数据 volatile unsigned int rsv3[3]; // 0x74/0x78/0x7C volatile unsigned char GPIOBit[0x40]; // 0x80~0xbf GPIO 位访问 } HW_PMU_t; #define PMU_CHIPCTRL *(volatile unsigned int *)(PMU_BASE+0x00) //全局配置 #define PMU_CMDSTS *(volatile unsigned int *)(PMU_BASE+0x04) //命令与状态 #define PMU_COUNT *(volatile unsigned int *)(PMU_BASE+0x08) //时间计数器 #define PMU_COMPARE *(volatile unsigned int *)(PMU_BASE+0x0c) //唤醒时间配置 #define AFIO_PORTA *(volatile unsigned int *)(PMU_BASE+0x10) //IO复用选择0 #define AFIO_PORTB *(volatile unsigned int *)(PMU_BASE+0x14) //IO复用选择1 #define AFIO_PORTC *(volatile unsigned int *)(PMU_BASE+0x18) //IO复用选择2 #define AFIO_PORTD *(volatile unsigned int *)(PMU_BASE+0x1c) //IO复用选择3 #define EXTI_EN *(volatile unsigned int *)(PMU_BASE+0x20) //外部中断使能 #define EXTI_POL *(volatile unsigned int *)(PMU_BASE+0x24) //外部中断极性 #define EXTI_EDGE *(volatile unsigned int *)(PMU_BASE+0x28) //外部中断边沿 #define EXTI_SRC *(volatile unsigned int *)(PMU_BASE+0x2c) //外部中断状态 #define PMU_WDTCFG *(volatile unsigned int *)(PMU_BASE+0x30) //看门狗配置 #define PMU_WDTFEED *(volatile unsigned int *)(PMU_BASE+0x34) //看门狗重置 #define PMU_POWERCFG *(volatile unsigned int *)(PMU_BASE+0x38) //电源配置 #define PMU_CMDW *(volatile unsigned int *)(PMU_BASE+0x3c) //Command写端口 #define PMU_GPIOA_OE *(volatile unsigned int *)(PMU_BASE+0x40) //GPIOA输出使能 #define PMU_GPIOA_O *(volatile unsigned int *)(PMU_BASE+0x44) //GPIOA输出电平 #define PMU_GPIOA_I *(volatile unsigned int *)(PMU_BASE+0x48) //GPIOA输入电平 #define PMU_GPIOB_OE *(volatile unsigned int *)(PMU_BASE+0x50) //GPIOB输出使能 #define PMU_GPIOB_O *(volatile unsigned int *)(PMU_BASE+0x54) //GPIOB输出电平 #define PMU_GPIOB_I *(volatile unsigned int *)(PMU_BASE+0x58) //GPIOB输入电平 #define PMU_Pulse0 *(volatile unsigned int *)(PMU_BASE+0x60) //脉冲输出配置0 #define PMU_Pulse1 *(volatile unsigned int *)(PMU_BASE+0x64) //脉冲输出配置1 #define PMU_UserDAT *(volatile unsigned int *)(PMU_BASE+0x68) //用户数据 #define PMU_AdcCtrl *(volatile unsigned int *)(PMU_BASE+0x6c) //ADC控制 #define PMU_AdcDat *(volatile unsigned int *)(PMU_BASE+0x70) //ADC数据 #define PMU_GPIOBit(i) *(volatile unsigned char *)(PMU_BASE+0x80+i) //GPIO位访问 /* • ChipCtrl 芯片全局配置 */ #define CHIPCTRL_SOFTFLAG_MASK (0xF<<28) /* 读写软件标志位 */ #define CHIPCTRL_SOFTFLAG_SHIFT 28 #define CHIPCTRL_TURBOEN bit(27) /* 1=当CPU在RAM中执行指令时, 频率提高至32MHZ */ #define CHIPCTRL_SPI_START bit(26) /* SPI 启动速率选择: 1=8us; 0=256us */ #define CHIPCTRL_BATDET_SEL_MASK (0x3<<24) /* 掉电信号检测选择 */ #define CHIPCTRL_BATDET_SEL_SHIFT 24 #define CHIPCTRL_BATDET_SEL_ADCI0 (0<<24) #define CHIPCTRL_BATDET_SEL_ADCI1 (1<<24) #define CHIPCTRL_BATDET_SEL_GPIO00 (2<<24) #define CHIPCTRL_BATDET_SEL_GPIO01 (3<<24) #define CHIPCTRL_ADCI7_EN bit(23) /* ADC_I[7] 模拟输入使能 */ #define CHIPCTRL_ADCI6_EN bit(22) /* =0: 数字输入, 可复用为GPIO */ #define CHIPCTRL_ADCI5_EN bit(21) /* =1: 模拟输入 */ #define CHIPCTRL_ADCI4_EN bit(20) #define CHIPCTRL_ADCIO_PU bit(19) /* ADC_IO 400K上拉, 0=关闭, 1=打开 */ #define CHIPCTRL_ADCIO_PD bit(18) /* ADC_IO 400K下拉, 0=关闭, 1=打开 */ #define CHIPCTRL_ADCIO_IEN bit(17) /* ADC_IO 数字输入使能, 0=关闭,引脚上模拟信号, 1=打开,引脚上数字信号 */ #define CHIPCTRL_ADC_POWERON bit(16) /* ADC 电源, 0=自动打开, 1=常开 */ #define CHIPCTRL_DRAM_POWERDOWN bit(15) /* DRAM 电源, 0=常开,休眠时有数据需要保存, 1=与CPU同时上下电 */ #define CHIPCTRL_UART2_OFF bit(14) /* 1=关断 */ #define CHIPCTRL_RTC_OFF bit(13) /* 1=关断 */ #define CHIPCTRL_TSENSOR_OFF bit(12) /* 1=关断 */ #define CHIPCTRL_FASTEN bit(11) /* 1=3分频; 0=4分频 */ #define CHIPCTRL_INPUT_HOLD bit(10) /* GPIO输入保持 */ #define CHIPCTRL_CLKUP_DELAY_MASK (0x3<<8) /* 高速晶振开启到可以使用的延迟 */ #define CHIPCTRL_CLKUP_DELAY_SHIFT 8 #define CHIPCTRL_CLKUP_DELAY_5140 (0<<8) #define CHIPCTRL_CLKUP_DELAY_480 (1<<8) #define CHIPCTRL_CLKUP_DELAY_1460 (2<<8) #define CHIPCTRL_CLKUP_DELAY_2440 (3<<8) #define CHIPCTRL_8M_SEL bit(7) /* 8M 时钟选择, 0=内部, 1=外部 */ #define CHIPCTRL_8M_EN bit(6) /* 高速晶体振荡器使能 */ #define CHIPCTRL_32K_SEL bit(5) /* 32K 时钟选择, 0=内部, 1=外部 */ #define CHIPCTRL_32K_SPEED bit(4) /* 内部 32K OSC 速度, 1: 1K, 0: 32K */ #define CHIPCTRL_32K_TRIM_MASK 0xF /* 内部32K OSC Trimming 值 */ /* • CmdSts 命令与状态 */ #define CMDSR_8M_FAIL bit(31) /* RO 8M 外部时钟失效, 1=失效 */ #define CMDSR_8M_SEL bit(30) /* RO 8M 时钟选择, 1=外部时钟 */ #define CMDSR_32K_FAIL bit(29) /* RO 32K 外部时钟失效, 1=失效 */ #define CMDSR_32K_SEL bit(28) /* RO 32K 时钟选择, 1=外部时钟 */ #define CMDSR_RSTSRC_MASK (0x3<<26) /* RO 复位来源 */ #define CMDSR_RSTSRC_SHIFT 26 #define CMDSR_RSTSRC_OUT (0<<26) /* 外部复位 */ #define CMDSR_RSTSRC_DOG0 (1<<26) /* 看门狗复位 */ #define CMDSR_RSTSRC_DOG1 (2<<26) /* 看门狗复位 */ #define CMDSR_RSTSRC_WAKE (3<<26) /* 休眠唤醒 */ #define CMDSR_EXINTEN bit(25) /* 外部中断使能, 1=有效 */ #define CMDSR_INTSRC_MASK (0x1FF<<16) /* bit[24:16] RO 中断状态 */ #define CMDSR_INTSRC_SHIFT 16 /* XXX 发生中断后对应位=1, 往CommandW寄存器对应位写1清除中断 */ #define CMDSR_INTSRC_EXTINT bit(24) #define CMDSR_INTSRC_ADC bit(23) #define CMDSR_INTSRC_RTC bit(22) #define CMDSR_INTSRC_8MFAIL bit(21) #define CMDSR_INTSRC_32KFAIL bit(20) #define CMDSR_INTSRC_BATFAIL bit(19) #define CMDSR_INTSRC_UART2 bit(18) /* ring */ #define CMDSR_INTSRC_TOUCH bit(17) #define CMDSR_INTSRC_WAKE bit(16) #define CMDSR_INTEN_MASK (0xFF<<8) /* bit[15:8] 中断使能, 每一位对应一个中断源*/ #define CMDSR_INTEN_SHIFT 8 #define CMDSR_INTEN_ADC bit(15) #define CMDSR_INTEN_RTC bit(14) #define CMDSR_INTEN_8MFAIL bit(13) #define CMDSR_INTEN_32KFAIL bit(12) #define CMDSR_INTEN_BATFAIL bit(11) #define CMDSR_INTEN_UART2 bit(10) #define CMDSR_INTEN_TOUCH bit(9) #define CMDSR_INTEN_WAKE bit(8) #define CMDSR_WAKE_EN bit(7) /* 定时唤醒使能, 0=关闭, 1=打开 */ #define CMDSR_SLEEP_EN bit(0) /* RO 进入休眠状态. 读出值为1表示可休眠, 往CommandW[0]写1则关闭处理器系统 */ /* • Count 时间计数器 */ #define COUNT_MASK 0x000FFFFF /* bit[19:0] 每1/256秒 +1 */ /* • Compare 唤醒时间配置 */ #define COMPARE_MASK 0x000FFFFF /* bit[19:0] 当该值与 Count 相等且 WakeEn 为 1时产生唤醒事件 */ /* • IOSEL0~3 GPIO 复用选择. • 共128位, 由低到高每 2 位控制一个 GPIO 的复位状态, 复位期间所有引脚配置为GPIO 输入. */ #define IOSEL_GPIO 0 #define IOSEL_MAIN 1 #define IOSEL_MUX1 2 #define IOSEL_MUX2 3 / EXTI REGS / typedef struct { uint32_t EXINT_EN; uint32_t EXINT_POL; uint32_t EXINT_EDGE; uint32_t EXINT_SRC; } EXTI_TypeDef; #define PMU_Exti (0x20) #define EXTI_BASE (PMU_BASE + PMU_Exti) #define EXTI ((EXTI_TypeDef *) EXTI_BASE) /* • ExIntEn 外部中断使能 * • bit[0:7] 对应GPIO0~GPIO7 • bit[8:15] 对应GPIO16~GPIO23 • bit[16:23] 对应GPIO32~GPIO39 • bit[24:31] 对应GPIO48~GPIO55 */ /* • ExIntPol 外部中断极性 * • 对应关系同上, 0=高电平/上升沿有效 */ /* • ExIntEdge 外部中断边沿 * • 对应关系同上, 0=电平模式, 1=边沿模式 */ /* • ExIntSrc 外部中断状态 * • 对应关系同上, 写1清除 */ /* • WdtCfg 看门狗配置 */ #define WDTCFG_HI_MASK 0xFFFF0000 /* bit[31:16], 其值等于低16位取反 */ #define WDTCFG_HI_SHIFT 16 #define WDTCFG_LO_MASK 0x0000FFFF /* bit[15:0], 看门狗复位等待时间, 以秒为单位. 最高位为奇校验位 */ /* • WdtFeed 喂狗 */ #define WDTFEED_FOOD 0xA55A55AA /* 喂狗值 */ /* • PowerCfg 电源配置 * • XXX 不建议修改 */ /* • CommandW 命令写端口, 以下位对应CmdSrc * • bit[23:16] IntSrc WO 写1清除中断标志 • bit[0] Sleep/SleepEn * * */ /* • GPIOA_OE/GPIOB_OE 输出使能 *0=输入; 1=输出 */ /* • GPIOA_O/GPIOB_O 输出 *0=低电平, 1=高电平. 输入状态时写1, 表示该引脚需要输入保持. */ /* • GPIOA_I/GPIOB_I 输入 *0=低电平, 1=高电平 */ /* • Pulse0/Pulse1 脉冲输出配置 * • XXX 改变时钟或分频系数时应该先关闭, 再打开. */ #define PULSE_ENABLE bit(17) /* 脉冲输出使能. 0=关闭, 引脚为GPIO功能, 1=开启,输出占空比50%脉冲 */ #define PULSE_CLK_SEL bit(16) /* 时钟源选择. 0=32K, 1=8M */ #define PULSE_MASK 0x0000FFFF /* 脉冲分频系数 */ /* • UserDat 用户数据 * • XXX 复位不会清除的数据 */ /* • AdcCtrl ADC 控制 */ #define ADCCTRL_RUN bit(8) /* 启动单次测量. 写1启动, 结束后自动清除; 产生ADC中断 */ #define ADCCTRL_DIV bit(4) /* 时钟分频选择. 0=2分频, 1=4分频 */ #define ADCCTRL_SEL_MASK 0x07 /* 通道选择 */ #define ADCCTRL_SEL_ADCI0 0 #define ADCCTRL_SEL_ADCI1 1 #define ADCCTRL_SEL_VCORE 2 #define ADCCTRL_SEL_1V 3 #define ADCCTRL_SEL_ADCI4 4 #define ADCCTRL_SEL_ADCI5 5 #define ADCCTRL_SEL_ADCI6 6 #define ADCCTRL_SEL_ADCI7 7 /* • AdcDat ADC 数据 */ #define ADCDAT_MASK 0x0FFF /* 12位有效位 */ /* • GPIOBit[0x40] GPIO 位访问端口 * • 每个字节对应一个端口 */ #define GPIOBIT_OE bit(1) /* GPIO方向. 0=输入, 1=输出 */ #define GPIOBIT_VAL bit(0) //------------------------------------------------------------------------------------------------- // 外部中断管理 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned char en; // 0x00 中断使能寄存器. 1=中断使能 volatile unsigned char edge; // 0x01 中断边沿寄存器. 1=边沿触发, 0=电平触发 volatile unsigned char pol; // 0x02 中断极性寄存器. 1=高电平/上升沿触发 volatile unsigned char clr; // 0x03 中断清除寄存器. 写1清除中断状态 volatile unsigned char set; // 0x04 中断置位寄存器. 写1置中断触发模式的中断状态, XXX 用于测试 volatile unsigned char out; // 0x05 中断输出寄存器. 1=中断触发 volatile unsigned char srprot; // 0x06 运行状态及保护寄存器 } HW_INTC_t; /* • 中断对应位域 */ #define INTC_DMA bit(7) /* DMA 中断位 */ #define INTC_VPWM bit(6) /* VPWM 中断位 */ #define INTC_SPI bit(5) /* SPI 中断位 */ #define INTC_FLASH bit(4) /* Flash 中断位 */ #define INTC_UART0 bit(3) /* UART0 中断位 */ #define INTC_UART1 bit(2) /* UART1 中断位 */ #define INTC_I2C bit(1) /* I2C 中断位 */ #define INTC_TIMER bit(0) /* 定时器中断位 */ /* • SRPROT 运行状态及保护寄存器 */ #define SRPROT_ADDR_CHECK_EN bit(7) /* 地址检查使能. 1=进行地址检查, 当软件发出未定义的地址时触发NMI中断, ▪ 往此寄存器连续写入 0x00, 0x5A, 0xA5 打开此位写使能. */ #define SRPROT_JTAG_LOCK bit(5) /* RO JTAG 锁定, 1=JTAG被禁用 */ #define SRPROT_OPT_LOCK bit(4) /* RO OTP 锁定, 1=OPT区域被禁用 */ #define SRPROT_NEW_PKG bit(3) /* RO 新封装模式 */ #define SRPROT_JTAG_MUX bit(2) /* RO JTAG 复用. 1=复用为GPIO */ #define SRPROT_INSTALL_MODE bit(1) /* RO 安装模式. 1=安装模式 */ #define SRPROT_BOOT_SPI bit(0) /* RO SPI 启动. 1=当前从SPI启动 */ / INTC REGS / typedef struct { volatile uint8_t INTC_EN; /* 中断使能寄存器 */ volatile uint8_t INTC_EDGE; /* 中断边沿寄存器 */ volatile uint8_t INTC_POL; /* 中断极性寄存器 */ volatile uint8_t INTC_CLR; /* 中断清除寄存器 */ volatile uint8_t INTC_SET; /* 中断置位寄存器 */ volatile uint8_t INTC_OUT; /* 中断输出寄存器 */ volatile uint8_t SRPRPT; /* 运行状态及保护寄存器 */ } INT_TypeDef; #define INTC_EN_OFFSET 0x0 #define INTC_EDGE_OFFSET 0x1 #define INTC_POL_OFFSET 0x2 #define INTC_CLR_OFFSET 0x3 #define INTC_SET_OFFSET 0x4 #define INTC_OUT_OFFSET 0x5 #define INTC_SRPROT_OFFSET 0x6 #define INTC_CKGATE_OFFSET 0x7 #define INT_EN *(volatile unsigned char *)(INTC_BASE+0x00) //中断使能寄存器 #define INT_EGDE *(volatile unsigned char *)(INTC_BASE+0x01) //中断边沿寄存器 #define INT_POL *(volatile unsigned char *)(INTC_BASE+0x02) //中断极性寄存器 #define INT_CLR *(volatile unsigned char *)(INTC_BASE+0x03) //中断清除寄存器 #define INT_SET *(volatile unsigned char *)(INTC_BASE+0x04) //中断置位寄存器 #define INT_OUT *(volatile unsigned char *)(INTC_BASE+0x05) //中断输出寄存器 #define INT_SRPROT *(volatile unsigned char *)(INTC_BASE+0x06) //运行状态及保护寄存 #define SRPROT INT_SRPROT #define INT ((INT_TypeDef *) INTC_BASE) / SPI REGS / typedef struct { volatile uint8_t SPCR; /* 控制寄存器 */ volatile uint8_t SPSR; /* 状态寄存器 */ volatile uint8_t DATA; /* 数据寄存器 */ volatile uint8_t SPER; /* 外部寄存器 */ volatile uint8_t PARAM; /* 参数控制寄存器 */ volatile uint8_t SOFTCS; /* 片选控制寄存器 */ volatile uint8_t TIMING; /* 时序控制寄存器 */ } SPI_TypeDef; #define SPI ((SPI_TypeDef *) SPI_BASE) #define SPI_SPCR *(volatile unsigned char *)(SPI_BASE+0x00) //控制寄存器 #define SPI_SPSR *(volatile unsigned char *)(SPI_BASE+0x01) //状态寄存器 #define SPI_TxFIFO *(volatile unsigned char *)(SPI_BASE+0x02) //数据寄存器 #define SPI_RxFIFO *(volatile unsigned char *)(SPI_BASE+0x02) //数据寄存器 #define SPI_SPER *(volatile unsigned char *)(SPI_BASE+0x03) //外部寄存器 #define SPI_SFC_PARAM *(volatile unsigned char *)(SPI_BASE+0x04) //参数控制寄存器 #define SPI_SFC_SOFTCS *(volatile unsigned char *)(SPI_BASE+0x05) //片选控制寄存器 #define SPI_SFC_TIMING *(volatile unsigned char *)(SPI_BASE+0x06) //时序控制寄存器 //------------------------------------------------------------------------------------------------- // 片内 Flash //------------------------------------------------------------------------------------------------- #define FLASH_PAGE_COUNT 1024 #define FLASH_PAGE_SIZE 128 #define FLASH_BYTES (1024*128) #define FLASH_OPT_ADDR 0xBF020000 typedef struct { volatile unsigned int cmd; // 0x00 命令寄存器 volatile unsigned int cah; // 0x04 加密地址上界寄存器 volatile unsigned int cal; // 0x08 加密地址下界寄存器 volatile unsigned int rsv; // 0x0C volatile unsigned int vrf; // 0x10 数据校验寄存器: 待校验数据 volatile unsigned int sts; // 0x14 状态寄存器 volatile unsigned int pet; // 0x18 擦写时间寄存器 } HW_FLASH_t; /* • CMD 命令寄存器 */ #define FLASH_CMD_CMD_MASK (0xF<<28) /* RW 命令 */ #define FLASH_CMD_CMD_SHIFT 28 #define FLASH_CMD_VERIFY (1<<28) /* 4’b0001 数据校验 */ #define FLASH_CMD_CLR_INT (3<<28) /* 4’b0011 清中断 */ #define FLASH_CMD_PAGE_LATCH (4<<28) /* 4’b0100 清page_latch */ #define FLASH_CMD_UPD_OPT (9<<28) /* 4’b1001 更新区域保护 */ #define FLASH_CMD_ERASE (10<<28) /* 4’b1010 擦除目标页 */ #define FLASH_CMD_SLEEP (12<<28) /* 4’b1100 进入休眠模式 */ #define FLASH_CMD_WRITE (14<<28) /* 4’b1110 编程目标页 */ #define FLASH_CMD_UPD_KEY (15<<28) /* 4’b1111 更新密钥 */ #define FLASH_CMD_PAGEADDR_MASK 0x0003FFFF /* 擦除或编程的目标页地址, 128k以内 */ /* • CAH 加密地址上界寄存器 */ #define FLASH_CADDR_HI_MASK 0x0003FFFF /* 加密范围的上界地址 */ /* • CAL 加密地址下界寄存器 */ #define FLASH_CADDR_LO_MASK 0x0003FFFF /* 加密范围的下界地址 */ /* • STS 状态寄存器 */ #define FLASH_SR_NO_PERMISSION bit(3) /* RO 无权限, 表示上一次操作无权限 */ #define FLASH_SR_PE_END bit(2) /* RO 擦写结束 */ #define FLASH_SR_VERIFY_END bit(1) /* RO 校验结束 */ #define FLASH_SR_VERIFY_OK bit(0) /* RO 校验正确 */ /* • PET 擦写时间寄存器 */ #define FLASH_PET_INTEN_NOPER bit(17) /* no_permission 中断使能 */ #define FLASH_PET_INTEN_PEEND bit(16) /* pe_end 中断使能 */ #define FLASH_PET_ETIME_MASK (7<<3) /* 擦除时间. 以8M时钟计算, 默认擦除时间2.5ms */ #define FLASH_PET_ETIME_SHIFT 3 #define FLASH_PET_ETIME_15 (0<<3) /* 0:1.5ms */ #define FLASH_PET_ETIME_20 (1<<3) /* 1:2.0ms */ #define FLASH_PET_ETIME_25 (2<<3) /* 2:2.5ms */ #define FLASH_PET_ETIME_30 (3<<3) /* 3:3.0ms */ #define FLASH_PET_ETIME_35 (4<<3) /* 4:3.5ms */ #define FLASH_PET_ETIME_40 (5<<3) /* 5:4.0ms */ #define FLASH_PET_ETIME_45 (6<<3) /* 6:4.5ms */ #define FLASH_PET_ETIME_50 (7<<3) /* 7:5.0ms */ #define FLASH_PET_PTIME_MASK 7 /* 编程时间. 以8M时钟计算, 默认编程时间2.5ms */ #define FLASH_PET_PTIME_15 0 /* 0:1.5ms */ #define FLASH_PET_PTIME_20 1 /* 1:2.0ms */ #define FLASH_PET_PTIME_25 2 /* 2:2.5ms */ #define FLASH_PET_PTIME_30 3 /* 3:3.0ms */ #define FLASH_PET_PTIME_35 4 /* 4:3.5ms */ #define FLASH_PET_PTIME_40 5 /* 5:4.0ms */ #define FLASH_PET_PTIME_45 6 /* 6:4.5ms */ #define FLASH_PET_PTIME_50 7 /* 7:5.0ms */ //------------------------------------------------------------------------------------------------- // 定时器 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned int cfg; // 0x00 配置寄存器 volatile unsigned int cnt; // 0x04 计数值寄存器 volatile unsigned int cmp; // 0x08 比较值寄存器 volatile unsigned int step; // 0x0c 步进值寄存器 } HW_TIMER_t; /* • CFG 配置寄存器, 用的 8M 时钟 */ #define TIMER_CFG_INT_SR bit(8) /* 中断状态/清中断. 1=有中断, 写1清中断 */ #define TIMER_CFG_PERIODIC bit(2) /* 1=周期触发 */ #define TIMER_CFG_INT_EN bit(1) /* 1=中断使能 */ #define TIMER_CFG_START bit(0) /* 1=计数使能, 此时不能修改 CNT/CMP/STP 的值 */ //------------------------------------------------------------------------------------------------- // I2C 控制器 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned char prerlo; // 0x00 分频值低字节寄存器 volatile unsigned char prerhi; // 0x01 分频值高字节寄存器 volatile unsigned char ctrl; // 0x02 控制寄存器 volatile unsigned char data; // 0x03 数据寄存器 union { volatile unsigned char cmd; // 0x04 命令寄存器 volatile unsigned char sr; // 0x04 状态寄存器 } CMDSR; volatile unsigned char blt; // 0x05 总线死锁时间寄存器 volatile unsigned char rsv; // 0x06 volatile unsigned char saddr; // 0x07 从模式地址寄存器 } HW_I2C_t; /* • PRERH 和 PRERL 共同组成分频值 PRER, 则输出的 SCL 频率为: clkin / (4*(PRER+1)) */ /* • CTL 控制寄存器 */ #define IIC_CTRL_EN bit(7) /* 模块工作使能. 1=正常工作模式, 0=对分频值寄存器进行操作 */ #define IIC_CTRL_IEN bit(6) /* 1=中断使能 */ #define IIC_CTRL_MASTER bit(5) /* 主从模式选择. 0=从设备, 1=主设备 */ #define IIC_CTRL_SLAVE_TXRDY bit(4) /* "从设备"发送数据准备好: 1=要发送的数据已写入data. 自动清零 */ #define IIC_CTRL_SLAVE_RXRDY bit(3) /* "从设备"接收数据已读出: 1=data内数据已被读出. 自动清零 */ #define IIC_CTRL_BUSLOCK_CHECK bit(1) /* 1=总线死锁状态检查使能: 时间buslock_top */ #define IIC_CTRL_SLAVE_ATUORST bit(0) /* 1=总线死锁时从设备自动复位状态机使能 */ /* • DATA 数据寄存器 * • 写入时为待发送数据, 读出时为收到的数据 */ /* • CMD 命令寄存器 */ #define IIC_CMD_START bit(7) /* 1="主设备"产生"传输开始波形" */ #define IIC_CMD_STOP bit(6) /* 1="主设备"产生"传输结束波形" */ #define IIC_CMD_READ bit(5) /* 1="主设备"下一次传输为总线读请求 */ #define IIC_CMD_WRITE bit(4) /* 1="主设备"下一次传输为总线写请求 */ #define IIC_CMD_NACK bit(3) /* 主设备应答. 1=下一次读数据返回时应答NACK, 连续读请求结束 */ #define IIC_CMD_ACK 0 #define IIC_CMD_RECOVER bit(2) /* 总线死锁恢复命令. 1="主设备"解除死锁 */ #define IIC_CMD_IACK bit(0) /* 中断应答. 写1清中断 */ /* • SR 状态寄存器 */ #define IIC_SR_RXNACK bit(7) /* 0=收到应答, 1=收到NACK */ #define IIC_SR_BUSY bit(6) /* 1=总线忙状态 */ #define IIC_SR_ALOST bit(5) /* 1="主设备"失去总线控制权 */ #define IIC_SR_SLAVE_ADDRESSED bit(4) /* 1="从设备"被寻址成功 */ #define IIC_SR_SLAVE_RW bit(3) /* 0="从设备"被读, 1="从设备"被写 */ #define IIC_SR_BUSLOCK bit(2) /* 1=总线死锁 */ #define IIC_SR_TXIP bit(1) /* 1="主设备"正在传输 */ #define IIC_SR_INT_FLAG bit(0) /* 中断标志位. 1=传输完1个字节或"主设备"丢失控制权 */ /* • SADDR 从模式地址寄存器 */ #define IIC_SADDR_MASK 0x7F /* 从设备地址 */ //------------------------------------------------------------------------------------------------- // SPI 控制器 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned char ctrl; // 0x00 控制寄存器 volatile unsigned char sr; // 0x01 状态寄存器 volatile unsigned char data; // 0x02 数据寄存器 volatile unsigned char er; // 0x03 外部寄存器 volatile unsigned char param; // 0x04 参数控制寄存器 volatile unsigned char cs; // 0x05 片选寄存器 volatile unsigned char timing; // 0x06 时序控制寄存器 } HW_SPI_t; /* • CTRL 控制寄存器 */ #define SPI_CTRL_INT_EN bit(7) /* 1=中断使能 */ #define SPI_CTRL_EN bit(6) /* 1=系统工作使能 */ #define SPI_CTRL_MASTER bit(4) /* 1=master 模式, 0=slave 模式 */ #define SPI_CTRL_CPOL bit(3) /* 时钟极性, 表示无时钟时 CLK 的电平. 1=高电平, 0=低电平 */ #define SPI_CTRL_CPHA bit(2) /* 时钟相位, 0=相位相同, 1=相位相反 */ #define SPI_CTRL_SPR_MASK 0x03 /* 时钟分频位, 与 SPER 一起使用 */ /* • SR 状态寄存器 */ #define SPI_SR_INT_FLAG bit(7) /* 1=有中断, 写1清零 */ #define SPI_SR_WCOL bit(6) /* "写寄存器"溢出标志位, 1=溢出, 写1清零 */ #define SPI_SR_BUSY bit(4) /* 1=控制器忙 */ #define SPI_SR_WFFULL bit(3) /* 1="写寄存器"满标志 */ #define SPI_SR_WFEMPTY bit(2) /* 1="写寄存器"空标志 */ #define SPI_SR_RFFULL bit(1) /* 1="读寄存器"满标志 */ #define SPI_SR_RFEMPTY bit(0) /* 1="读寄存器"空标志 */ /* • SPER 外部寄存器 */ #define SPI_ER_INT_CNT_MASK 0xC0 /* 传输多少字节后发中断 */ #define SPI_ER_INT_CNT_SHIFT 6 #define SPI_ER_INT_1BYTES 0 #define SPI_ER_INT_2BYTES 1 #define SPI_ER_INT_3BYTES 2 #define SPI_ER_INT_4BYTES 3 #define SPI_ER_MODE bit(2) /* 接口模式. 0:采样与发送时机同步, 1:采样与发送时机错开半周期 */ #define SPI_ER_SPRE_MASK 0x03 /* 时钟分频位. 与SPR 一起设定分频比率 */ #if 0 #define SPI_ER_SPRE_2 0 /* 4’b0000 */ #define SPI_ER_SPRE_4 1 /* 4’b0001 */ #define SPI_ER_SPRE_16 2 /* 4’b0010 */ #define SPI_ER_SPRE_32 3 /* 4’b0011 */ #define SPI_ER_SPRE_8 4 /* 4’b0100 */ #define SPI_ER_SPRE_64 5 /* 4’b0101 */ #define SPI_ER_SPRE_128 6 /* 4’b0110 */ #define SPI_ER_SPRE_256 7 /* 4’b0111 */ #define SPI_ER_SPRE_512 8 /* 4’b1000 */ #define SPI_ER_SPRE_1024 9 /* 4’b1001 */ #define SPI_ER_SPRE_2048 10 /* 4’b1010 */ #define SPI_ER_SPRE_4096 11 /* 4’b1011 */ #endif /* • PARAM 参数控制寄存器 */ #define SPI_PARAM_CLKDIV_MASK 0xF0 /* 时钟分频数选择: 与{spre,spr}组合相同 */ #define SPI_PARAM_DUALIO bit(3) /* 双IO 模式, 优先级高于fast_read */ #define SPI_PARAM_FASTREAD bit(2) /* 快速读模式 */ #define SPI_PARAM_BURST_EN bit(1) /* SPI Flash 支持连续地址读模式 */ #define SPI_PARAM_MEMORY_EN bit(0) /* SPI Flash 读使能. 0=可通过CS0控制Flash读写 */ /* • CS 片选控制寄存器 */ #define SPI_CS_MASK 0xF0 /* 片选 */ #define SPI_CS_SHIFT 4 #define SPI_CS_FLASH 0x10 /* 片选 Flash */ #define SPI_CS_1 0x20 #define SPI_CS_2 0x40 #define SPI_CS_3 0x80 #define SPI_CS_EN_MASK 0x0F /* 片选使能, 高有效 */ #define SPI_CS_EN_FLASH 0x01 /* 使能片选 Flash */ #define SPI_CS_EN_1 0x02 #define SPI_CS_EN_2 0x04 #define SPI_CS_EN_3 0x08 /* • TIMING 时序控制寄存器 */ #define SPI_TIMING_FAST bit(2) /* SPI flash 读采样模式. 0=上沿采样,间隔半个SPI周期; 1=上沿采样,间隔1个SPI周期*/ #define SPI_TIMING_CSH_MASK 0x03 /* SPI flash 片选信号最短无效时间, 以分频后的时钟周期T计算 */ #define SPI_TIMING_CSH_1T 0 #define SPI_TIMING_CSH_2T 1 #define SPI_TIMING_CSH_4T 2 #define SPI_TIMING_CSH_8T 3 //------------------------------------------------------------------------------------------------- // UART 控制器 //------------------------------------------------------------------------------------------------- /* • XXX UART0/1 使用8M时钟, UART2 使用 32K 时钟 */ #define NS16550_FIFO_SIZE 16 /* XXX 16 bytes? */ typedef struct { union { volatile unsigned char dat; // 0x00 数据寄存器 volatile unsigned char dll; // 0x00 分频值低字节寄存器 } R0; union { volatile unsigned char ier; // 0x01 中断使能寄存器 volatile unsigned char dlh; // 0x01 分频值高字节寄存器 } R1; union { volatile unsigned char isr; // 0x02 中断状态寄存器 volatile unsigned char fcr; // 0x02 FIFO控制寄存器 volatile unsigned char dld; // 0x02 分频值小数寄存器 } R2; volatile unsigned char lcr; // 0x03 线路控制寄存器 volatile unsigned char samp; // 0x04 bit 窗口划分和采样控制寄存器 volatile unsigned char lsr; // 0x05 线路状态寄存器 volatile unsigned char tfcnt; // 0x06 发送队列数据存量 volatile unsigned char sr; // 0x07 状态寄存器 } HW_NS16550_t; /* • IER 中断使能寄存器 */ #define NS16550_IER_MODEM bit(3) /* Modem 状态中断使能 */ #define NS16550_IER_LINE bit(2) /* 线路状态中断使能 */ #define NS16550_IER_TX bit(1) /* 发送状态中断使能 */ #define NS16550_IER_RX bit(0) /* 接收状态中断使能 */ /* • ISR 中断状态寄存器 */ #define NS16550_ISR_SRC_MASK 0x0E /* RO 中断源 */ #define NS16550_ISR_SRC_SHIFT 1 #define NS16550_ISR_LINE (0x3<<1) /* 3’b011 线路状态中断, 优先级1, 奇偶/溢出/帧错误/打断时中断, 读LSR清除 */ #define NS16550_ISR_RX (0x2<<2) /* 3’b010 接收状态中断, 优先级2, RX数量达到trigger的值, 读data清除 */ #define NS16550_ISR_RXTMO (0x6<<1) /* 3’b110 接收状态中断, 优先级2, RX超时, 读data清除 */ #define NS16550_ISR_TX (0x1<<1) /* 3’b001 发送状态中断, 优先级3, TX FIFO为空, 写data或读isr清除 */ #define NS16550_ISR_MODEM (0x0<<1) /* 3’b000 Modem状态中断, 优先级4, reserved, 读 Modem状态寄存器清除 */ #define NS16550_ISR_PENDING bit(0) /* 中断未决状态 */ /* • FCR FIFO 控制寄存器 */ #define NS16550_FCR_TRIG_MASK 0xF8 /* 接收中断状态所需trigger. 0/1=1字节, 最多16字节 */ #define NS16550_FCR_TRIG_SHIFT 3 #define NS16550_FCR_TRIGGER(n) ((n<<3)&NS16550_FCR_TRIG_MASK) #define NS16550_FCR_TXFIFO_RST bit(2) /* 复位发送FIFO */ #define NS16550_FCR_RXFIFO_RST bit(1) /* 复位接收FIFO */ #define NS16550_FCR_FIFO_EN bit(0) /* 使能FIFO? */ /* • LCR 线路控制寄存器 */ #define NS16550_LCR_DLAB bit(7) /* 分频器模式. 0=访问正常寄存器, 1=访问分频寄存器 */ #define NS16550_LCR_BCB bit(6) /* 打断控制位. 0=正常操作, 1=串口输出置0(打断状态) */ #define NS16550_LCR_SPD bit(5) /* 指定奇偶校验位. 0:不指定奇偶校验位, 1: eps=1则校验位为0, eps=0则校验位为1 */ #define NS16550_LCR_EPS bit(4) /* 奇偶校验位选择. 0=奇校验, 1=偶校验 */ #define NS16550_LCR_PE bit(3) /* 1=奇偶校验位使能 */ #define NS16550_LCR_SB bit(2) /* 生成停止位位数. 0:1个停止位, 1:bec=5时1.5个停止位, 其它2个停止位 */ #define NS16550_LCR_BITS_MASK 0x03 /* 字符位数 */ #define NS16550_LCR_BITS_5 0 #define NS16550_LCR_BITS_6 1 #define NS16550_LCR_BITS_7 2 #define NS16550_LCR_BITS_8 3 /* • LSR 线路状态寄存器 */ #define NS16550_LSR_ERR bit(7) /* 1=有错误, 校验/帧错误或打断中断 */ #define NS16550_LSR_TE bit(6) /* 0=有数据, 1=TX FIFO和传输移位寄存器为空. 写TXFIFO时清除 */ #define NS16550_LSR_TFE bit(5) /* 1=传输 FIFO 为空 */ #define NS16550_LSR_BI bit(4) /* 打断中断. 0=没有中断 */ #define NS16550_LSR_FE bit(3) /* 帧错误 */ #define NS16550_LSR_PE bit(2) /* 奇偶校验位错误 */ #define NS16550_LSR_OE bit(1) /* 数据溢出 */ #define NS16550_LSR_DR bit(0) /* 接收数据有效. 0=RXFIFO无数据, 1=RXFIFO有数据 */ /* • TF_CNT 发送队列中待发送的数据量 */ #define NS16550_TFCNT_LOOPBACK bit(7) /* 自回环模式控制位 */ #define NS16550_TFCNT_MASK 0x1F /* 发送队列中待发送的数据量 */ /* • SR 状态寄存器寄存器 */ #define NS16550_SR_RX_RST bit(7) /* 接收数据通路中32K 时钟域的复位状态. 1=正在复位 */ #define NS16550_SR_CLK32K_RST bit(6) /* 控制逻辑32K 时钟域的复位状态. 1=正在复位 */ #define NS16550_SR_FLUSH_WAIT bit(5) /* 接收数据通路中数据丢弃等待标识. 1=正在丢弃 */ #define NS16550_SR_RFCNT_MASK 0x1F /* 接收队列中的数据量 */ //------------------------------------------------------------------------------------------------- // 实时时钟 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned int freq; // 0x00 分频值寄存器 volatile unsigned int cfg; // 0x04 配置寄存器 volatile unsigned int rtc0; // 0x08 时间值寄存器0 volatile unsigned int rtc1; // 0x0C 时间值寄存器1 } HW_RTC_t; /* • FREQ 分频值寄存器, freqscale = freq_in/16 */ #define RTC_FREQ_I_MASK 0x0FFF0000 /* bit[27:16], 分频系数整数部分 */ #define RTC_FREQ_I_SHIFT 16 #define RTC_FREQ_F_MASK 0x0000FFC0 /* bit[15:6], 分频系数小数部分 */ #define RTC_FREQ_F_SHIFT 6 /* • CFG 配置寄存器 */ #define RTC_CFG_STATE bit(31) /* 操作进行状态. 1=读写操作执行中, 写1清零, 用于硬件调试 */ #define RTC_CFG_TIMER_EN bit(30) /* 定时器使能. 1=使能, 时间到后自动清零 */ #define RTC_CFG_MONTH_MASK 0x3C000000 /* bit[29:26] 月 */ #define RTC_CFG_MONTH_SHIFT 26 #define RTC_CFG_DAY_MASK 0x03E00000 /* bit[25:21] 日 */ #define RTC_CFG_DAY_SHIFT 21 #define RTC_CFG_HOUR_MASK 0x001F0000 /* bit[20:16] 时 */ #define RTC_CFG_HOUR_SHIFT 16 #define RTC_CFG_MINUTE_MASK 0x0000FC00 /* bit[15:10] 分 */ #define RTC_CFG_MINUTE_SHIFT 10 #define RTC_CFG_SECOND_MASK 0x000003F0 /* bit[9:4] 秒 */ #define RTC_CFG_SECOND_SHIFT 4 #define RTC_CFG_SIXTEENTH_MASK 0x0000000F /* bit[3:0] 十六分之一秒 */ #define RTC_CFG_SIXTEENTH_SHIFT 0 /* • RTC0 时间值寄存器0 */ #define RTC0_BAD_TIME bit(31) /* 无效数值 */ #define RTC0_HOUR_MASK 0x001F0000 /* bit[20:16] 时 */ #define RTC0_HOUR_SHIFT 16 #define RTC0_MINUTE_MASK 0x0000FC00 /* bit[15:10] 分 */ #define RTC0_MINUTE_SHIFT 10 #define RTC0_SECOND_MASK 0x000003F0 /* bit[9:4] 秒 */ #define RTC0_SECOND_SHIFT 4 #define RTC0_SIXTEENTH_MASK 0x0000000F /* bit[3:0] 十六分之一秒 */ #define RTC0_SIXTEENTH_SHIFT 0 /* • RTC1 时间值寄存器1 */ #define RTC1_BAD_TIME bit(31) /* 无效数值 */ #define RTC1_YEAR_MASK 0x0000FE00 /* bit[15:9] 年, 从2000年起 */ #define RTC1_YEAR_SHIFT 9 #define RTC1_MONTH_MASK 0x000001E0 /* bit[8:5] 月 */ #define RTC1_MONTH_SHIFT 5 #define RTC1_DAY_MASK 0x0000001F /* bit[4:0] 日 */ #define RTC1_DAY_SHIFT 0 //------------------------------------------------------------------------------------------------- // DMA 控制器 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned int source; // 0x00 DMA 命令源地址读写端口. 动态变化 volatile unsigned int count; // 0x04 DMA 命令数据长度读写端口, 搬运的字数, 动态变化 volatile unsigned int cmd_sr; // 0x08 命令和状态寄存器 volatile unsigned int int_sr; // 0x0c 中断和状态寄存器 volatile unsigned int src0; // 0x10 命令队列项 0 的源地址参数 volatile unsigned int src1; // 0x14 命令队列项1的源地址参数 volatile unsigned int cnt0; // 0x18 命令队列项 0 的DMA长度参数 volatile unsigned int cnt1; // 0x1c 命令队列项 1 的DMA长度参数 } HW_DMA_t; /* • SMD & STATUS 命令和状态寄存器 */ #define DMA_CMDSR_SOFT_RST bit(31) /* DMA 控制器软复位. 写1复位, 完成自动清零 */ #define DMA_CMDSR_IND_1ST bit(1) /* 标识DMA 的第一个数据 */ #define DMA_CMDSR_EN bit(0) /* DMA 命令生效 */ /*INT & STATUS 中断和状态寄存器 */ #define DMA_INTSR_BUF_RPTR bit(19) /* DMA 数据缓冲的读指针值 */ #define DMA_INTSR_BUF_WPTR bit(18) /* DMA 数据缓冲的写指针值 */ #define DMA_INTSR_BUFCNT_MASK 0x00030000 /* DMA 数据缓冲存储的有效数据项数 */ #define DMA_INTSR_BUFCNT_SHIFT 16 #define DMA_INTSR_CMD_RPTR bit(13) /* DMA 命令队列的读指针值 */ #define DMA_INTSR_CMD_WPTR bit(12) /* DMA 命令队列的写指针值 */ #define DMA_INTSR_CMD1_MASK 0x00000C00 /* bit[11:10] DMA 命令队列1 的命令值 */ #define DMA_INTSR_CMD1_SHIFT 10 #define DMA_INTSR_CMD1_INVALID (0<<10) /* 命令无效 */ #define DMA_INTSR_CMD1_NO_1ST (1<<10) /* 命令有效, 执行时不需要表示第一个数据 */ #define DMA_INTSR_CMD1_IND_1ST (3<<10) /* 命令有效, 执行时需要表示第一个数据 */ #define DMA_INTSR_CMD0_MASK 0x00000C00 /* bit[9:8] DMA 命令队列0 的命令值 */ #define DMA_INTSR_CMD0_SHIFT 8 #define DMA_INTSR_CMD0_INVALID (0<<8) /* 命令无效 */ #define DMA_INTSR_CMD0_NO_1ST (1<<8) /* 命令有效, 执行时不需要表示第一个数据 */ #define DMA_INTSR_CMD0_IND_1ST (3<<8) /* 命令有效, 执行时需要表示第一个数据 */ #define DMA_INTSR_INT_CNT_MASK 0x03 /* bit[1:0] 中断计数器 */ #define DMA_INTSR_INT_CLR bit(0) /* 每写入1,int_cnt-=1, 当=0时, 清除中断 */ //------------------------------------------------------------------------------------------------- // VPWM 模块 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned int cfg; // 0x00 算法配置 volatile unsigned int rsv; // 0x04 volatile unsigned int sr; // 0x08 数据写端口状态 volatile unsigned int data; // 0x0C 数据写端口 } HW_VPWM_t; /* • VPWMCFG 算法配置 */ #define VPWM_CFG_FORCEOUT bit(31) /* 强制输出 */ #define VPWM_CFG_OUT_INV bit(30) /* 输出取反 */ #define VPWM_CFG_OUT_DLY bit(29) /* 输出延迟 */ #define VPWM_CFG_OUT_DUAL bit(28) /* 输出模式 */ #define VPWM_CFG_FREQ_SEL bit(27) /* 时钟选择. 0=32M, 1=8M */ #define VPWM_CFG_FREQ_RSTn bit(26) /* 时钟复位. */ #define VPWM_CFG_UPSAMP_MASK 0x03000000 /* bit[25:24] 上采样系数 */ #define VPWM_CFG_UPSAMP_SHIFT 24 #define VPWM_CFG_OUTBITS_MASK 0x00F00000 /* bit[23:20] 输出数据位数 */ #define VPWM_CFG_OUTBITS_SHIFT 20 #define VPWM_CFG_DMA_EN bit(19) /* DMA 使能 */ #define VPWM_CFG_ADPCM_EN bit(16) /* ADPCM 压缩使能 */ #define VPWM_CFG_PWM_PER_MASK 0x0000FFF0 /* PWM 周期 */ #define VPWM_CFG_PWM_PER_SHIFT 4 #define VPWM_CFG_VOLUME_MASK 0x07 /* 音量 */ /* • AUDIO STATUS 数据写端口状态 */ #define VPWM_SR_UNDERFLOW bit(2) /* 缓存区下溢 */ #define VPWM_SR_FIRST_DATA bit(1) /* 第一个数据 */ #define VPWM_SR_READY bit(0) /* 读请求. 1=VPWM向处理器发送读请求 */ /* • AUDIO DATA 数据写端口: 当配置为通过寄存器接口获取数据时, 软件将音频数据写入该寄存器 */ //------------------------------------------------------------------------------------------------- // TSENSOR 触摸按键控制器 //------------------------------------------------------------------------------------------------- typedef struct { volatile unsigned int ctrl; // 0x00 控制寄存器 volatile unsigned int sr; // 0x04 状态寄存器 volatile unsigned int osc_th; // 0x08 环振/阀值寄存器 volatile unsigned int polltim; // 0x0c 扫描时序寄存器 volatile unsigned int rsv1[12]; // 0x10~0x3C volatile unsigned int chnl_attr[12]; // 0x40~0x6c 通道特征0~11 volatile unsigned int rsv2[4]; // 0x70~0x7C volatile unsigned int cnt_res[12]; // 0x80~0xac 计数结果0~11 } HW_TSENSOR_t; /* • TS-CTRL 控制寄存器 */ #define TS_CTRL_CHNLEN_MASK 0x0FFF0000 /* bit[27:16] 扫描对应位为1的通道 */ #define TS_CTRL_CHNLEN_SHIFT 16 #define TS_CTRL_DBC_EN bit(15) /* 去抖使能 */ #define TS_CTRL_DBC_NUM_MASK 0x00007000 /* bit[14:12] 去抖计数, 连续检测到 0~7 次按键才发中断 */ #define TS_CTRL_DBC_NUM_SHIFT 12 #define TS_CTRL_EOS_OV bit(11) /* 扫描结束强制溢出 */ #define TS_CTRL_FLT_LVL_MASK 0x00000300 /* bit[9:8] 基线滤波强度 */ #define TS_CTRL_FLT_LVL_SHIFT 8 #define TS_CTRL_IEN_MASM 0x000000F0 /* bit[7:4] 中断使能 */ #define TS_CTRL_IEN_SHIFT 4 #define TS_CTRL_IEN_OFLOW bit(7) /* 计数溢出中断使能 */ #define TS_CTRL_IEN_MULTI_DOWN bit(6) /* 多键同按中断使能 */ #define TS_CTRL_IEN_UP bit(5) /* 抬起中断使能 */ #define TS_CTRL_IEN_DOWN bit(4) /* 按下中断使能 */ #define TS_CTRL_TEST_EN bit(3) /* 测试模式 */ #define TS_CTRL_POLL_EN bit(1) /* 循环扫描使能 */ #define TS_CTRL_SCAN_EN bit(0) /* 单次扫描使能 */ /* • TS-STATE 状态寄存器 */ #define TS_SR_KEYCODE_MASK 0x0FFF0000 /* bit[27:16] 按键编码状态 */ #define TS_SR_KEYCODE_SHIFT 16 #define TS_SR_PSM_MASK 0x00000C00 /* bit[11:10] 循环状态 */ #define TS_SR_PSM_SHIFT 10 #define TS_SR_WSM_MASK 0x00000300 /* bit[9:8] 等待状态 */ #define TS_SR_WSM_SHIFT 8 #define TS_SR_SSM_MASK 0x000000F0 /* bit[7:4] 扫描状态 */ #define TS_SR_SSM_SHIFT 4 #define TS_SR_OVERFLOW bit(3) /* 计数溢出 */ #define TS_SR_MULTI_DOWN bit(2) /* 多键同按 */ #define TS_SR_UP bit(1) /* 所有键抬起 */ #define TS_SR_DOWN bit(0) /* 单键按下 */ /* • OSC-THRESH 环振/阀值寄存器 */ #define TS_OSCTH_UP_TH_MASK 0xFF000000 /* bit[31:24] 按键抬起阀值 */ #define TS_OSCTH_UP_TH_SHIFT 24 #define TS_OSCTH_BAS_TH_MASK 0x00F00000 /* bit[23:16] 基线滤波阀值 */ #define TS_OSCTH_BAS_TH_SHIFT 16 #define TS_CFG_CNT_NEG bit(15) /* 使用双沿计数 */ #define TS_CFG_CNT_PRD_MASK 0x00001F00 /* bit[12:8] 计数长度, 以32K时钟周期为单位? */ #define TS_CFG_CNT_PRD_SHIFT 8 #define TS_CFG_RSEL_MASK 0x0000000F /* bit[3:0] 电阻选择, 1~14=1K~14K */ /* • PollTim 扫描时序寄存器 */ #define TS_POLL_DBC_PRD_MASK 0xFF000000 /* bit[31:24] 去抖测量间隔, 以32K时钟周期为单位, 0=256 */ #define TS_POLL_DBC_PRD_SHIFT 24 #define TS_POLL_ACT_STB_MASK 0x00C00000 /* bit[23:22] 强制切换扫描模式 */ #define TS_POLL_ACT_STB_SHIFT 22 #define TS_POLL_ACTIVE bit(23) #define TS_POLL_STANDBY bit(22) #define TS_POLL_STB_PRD_MASK 0x003F0000 /* bit[21:16] 待机模式间隔, 以激活模式扫描周期为单位, 0=256 */ #define TS_POLL_STB_PRD_SHIFT 16 #define TS_POLL_ACT_PRD_MASK 0x00000F00 /* bit[11:8] 激活模式间隔, 以256个32K时钟为单位, 0=2^12 */ #define TS_POLL_ACT_PRD_SHIFT 8 #define TS_POLL_ACT_NUM_MASK 0x000000FF /* bit[7:0] 激活模式持续时间, 以待机模式周期为单位, 0=4 */ /* • Channel Attribute 按键通道特征值寄存器 */ #define TS_CHNLATTR_PRESS_MASK 0xFF000000 /* bit[31:24] 按键通道按下阈值 */ #define TS_CHNLATTR_PRESS_SHIFT 24 #define TS_CHNLATTR_BASVAL_MASK 0x00000FFF /* bit[11:0] 按键通道计数基准值 */ /* • Count Result 计数结果0~11 */ #define TS_RES_CNT_OV bit(31) /* 计数溢出 */ #define TS_RES_BAS_OV bit(30) /* 基线溢出 */ #define TS_RES_VAL_MASK 0x00000FFF /* bit[11:0] 计数值, 经修正或原始值 */ //------------------------------------------------------------------------------------------------- // ioctl command for spi & iic bus //------------------------------------------------------------------------------------------------- #define IOCTL_SPI_I2C_SET_TFRMODE 0x1000 #define IOCTL_FLASH_FAST_READ_ENABLE 0x2000 // none. - set spi flash param to memory-en #define IOCTL_FLASH_FAST_READ_DISABLE 0x4000 // none. - unset spi flash param to memory-en #define IOCTL_FLASH_GET_FAST_READ_MODE 0x8000 // unsigned int * - get spi flash is set to memory-en #define assert_param(expr) ((void)0) #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* LS1C102_H_ */ #ifndef _NS16550_H #define _NS16550_H #include "ls1c102.h" //----------------------------------------------------------------------------- #define CFLAG_TO_BAUDRATE(flag) \ ((flag == B1200) ? 1200 : \ (flag == B2400) ? 2400 : \ (flag == B4800) ? 4800 : \ (flag == B9600) ? 9600 : \ (flag == B19200) ? 19200 : \ (flag == B38400) ? 38400 : \ (flag == B57600) ? 57600 : \ (flag == B115200) ? 115200 : 9600) #define BAUDRATE_TO_CFLAG(baud) \ ((baud == 1200) ? B1200 : \ (baud == 2400) ? B2400 : \ (baud == 4800) ? B4800 : \ (baud == 9600) ? B9600 : \ (baud == 19200) ? B19200 : \ (baud == 38400) ? B38400 : \ (baud == 57600) ? B57600 : \ (baud == 115200) ? B115200 : B9600) //----------------------------------------------------------------------------- #define UART_BUF_SIZE 64 typedef struct { char Buf[UART_BUF_SIZE]; int Count; char *pHead; char *pTail; } NS16550_buf_t; typedef struct { HW_NS16550_t *hwUART; bool bInterrupt; unsigned int irqNum; int baudRate; NS16550_buf_t rx_buf; NS16550_buf_t tx_buf; } UART_t; //----------------------------------------------------------------------------- // UART devices //----------------------------------------------------------------------------- #if (BSP_USE_UART0) extern UART_t *devUART0; #endif #if (BSP_USE_UART1) extern UART_t *devUART1; #endif #if (BSP_USE_UART2) extern UART_t *devUART2; #endif //----------------------------------------------------------------------------- /* • NS16550 io control command param type */ #define IOC_NS16550_SET_MODE 0x1000 // struct termios * //----------------------------------------------------------------------------- // UART function //----------------------------------------------------------------------------- int NS16550_init(void *dev, void *arg, uint32_t uart_num); int NS16550_open(void *dev, void *arg, uint32_t uart_num); int NS16550_close(void *dev, void *arg); int NS16550_read(void *dev, unsigned char *buf, int size, void *arg); int NS16550_write(void *dev, unsigned char *buf, int size, void *arg); //int NS16550_ioctl(void *dev, unsigned cmd, void *arg); //----------------------------------------------------------------------------- // UART as Console //----------------------------------------------------------------------------- extern UART_t *ConsolePort; extern UART_t *ConsolePort0;// my extern UART_t *ConsolePort2;// my char Console_get_char(UART_t *pUART); void Console_output_char(UART_t *pUART, char ch); #endif // _NS16550_H #ifndef __CONSOLE_H__ #define __CONSOLE_H__ #ifdef __cplusplus extern "C" { #endif #include "ls1c102.h" void console_init(unsigned int baudrate); char console_getch(uint32_t uart_num); void console_putch(char ch, uint32_t uart_num); void console_putstr(char *s, uint32_t uart_num); void console0_init(unsigned int baudrate); void console2_init(unsigned int baudrate); void USART_SendData(char *buf_all, int uart_rx_count, uint32_t uart_num); #ifdef __cplusplus } #endif #endif /*__CONSOLE_H__*/ 根据这个工程目录和发送的代码,在loongide下写串口a发送1给串口b,串口b打印1,串口b发送2串口a打印2
06-30
/****************************************************************************/ /* */ /* 音频测试:MIC_IN读取音频数据,从LINE_OUT播出 */ /* */ /* 2014年7月1日 */ /* */ /****************************************************************************/ #include "TL6748.h" // 创龙 DSP6748 开发板相关声明 #include "edma_event.h" #include "interrupt.h" #include "soc_OMAPL138.h" #include "hw_syscfg0_OMAPL138.h" #include "codecif.h" #include "mcasp.h" #include "aic31.h" #include "edma.h" #include "psc.h" #include "uartStdio.h" #include <string.h> /****************************************************************************** ** 宏定义 *******************************************************************************/ /* ** Values which are configurable */ /* Slot size to send/receive data */ #define SLOT_SIZE (16u) /* Word size to send/receive data. Word size <= Slot size */ #define WORD_SIZE (16u) /* Sampling Rate which will be used by both transmit and receive sections */ #define SAMPLING_RATE (48000u) /* Number of channels, L & R */ #define NUM_I2S_CHANNELS (2u) /* Number of samples to be used per audio buffer */ #define NUM_SAMPLES_PER_AUDIO_BUF (2000u) /* Number of buffers used per tx/rx */ #define NUM_BUF (3u) /* Number of linked parameter set used per tx/rx */ #define NUM_PAR (2u) /* Specify where the parameter set starting is */ #define PAR_ID_START (40u) /* Number of samples in loop buffer */ #define NUM_SAMPLES_LOOP_BUF (10u) /* AIC3106 codec address */ #define I2C_SLAVE_CODEC_AIC31 (0x18u) /* Interrupt channels to map in AINTC */ #define INT_CHANNEL_I2C (2u) #define INT_CHANNEL_MCASP (2u) #define INT_CHANNEL_EDMACC (2u) /* McASP Serializer for Receive */ #define MCASP_XSER_RX (12u) /* McASP Serializer for Transmit */ #define MCASP_XSER_TX (11u) /* ** Below Macros are calculated based on the above inputs */ #define NUM_TX_SERIALIZERS ((NUM_I2S_CHANNELS >> 1) \ + (NUM_I2S_CHANNELS & 0x01)) #define NUM_RX_SERIALIZERS ((NUM_I2S_CHANNELS >> 1) \ + (NUM_I2S_CHANNELS & 0x01)) #define I2S_SLOTS ((1 << NUM_I2S_CHANNELS) - 1) #define BYTES_PER_SAMPLE ((WORD_SIZE >> 3) \ * NUM_I2S_CHANNELS) #define AUDIO_BUF_SIZE (NUM_SAMPLES_PER_AUDIO_BUF \ * BYTES_PER_SAMPLE) #define TX_DMA_INT_ENABLE (EDMA3CC_OPT_TCC_SET(1) | (1 \ << EDMA3CC_OPT_TCINTEN_SHIFT)) #define RX_DMA_INT_ENABLE (EDMA3CC_OPT_TCC_SET(0) | (1 \ << EDMA3CC_OPT_TCINTEN_SHIFT)) #define PAR_RX_START (PAR_ID_START) #define PAR_TX_START (PAR_RX_START + NUM_PAR) /* ** Definitions which are not configurable */ #define SIZE_PARAMSET (32u) #define OPT_FIFO_WIDTH (0x02 << 8u) /****************************************************************************** ** 函数原型声明 *******************************************************************************/ static void McASPErrorIsr(void); static void McASPErrorIntSetup(void); static void AIC31I2SConfigure(void); static void McASPI2SConfigure(void); static void McASPTxDMAComplHandler(void); static void McASPRxDMAComplHandler(void); static void EDMA3CCComplIsr(void); static void I2SDataTxRxActivate(void); static void I2SDMAParamInit(void); static void ParamTxLoopJobSet(unsigned short parId); static void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples, unsigned short parToUpdate, unsigned short linkAddr); static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId, unsigned short parLink); /****************************************************************************/ /* 全局变量 */ /****************************************************************************/ static unsigned char loopBuf[NUM_SAMPLES_LOOP_BUF * BYTES_PER_SAMPLE] = {0}; /* ** Transmit buffers. If any new buffer is to be added, define it here and ** update the NUM_BUF. */ static unsigned char txBuf0[AUDIO_BUF_SIZE]; static unsigned char txBuf1[AUDIO_BUF_SIZE]; static unsigned char txBuf2[AUDIO_BUF_SIZE]; /* ** Receive buffers. If any new buffer is to be added, define it here and ** update the NUM_BUF. */ static unsigned char rxBuf0[AUDIO_BUF_SIZE]; static unsigned char rxBuf1[AUDIO_BUF_SIZE]; static unsigned char rxBuf2[AUDIO_BUF_SIZE]; /* ** Next buffer to receive data. The data will be received in this buffer. */ static volatile unsigned int nxtBufToRcv = 0; /* ** The RX buffer which filled latest. */ static volatile unsigned int lastFullRxBuf = 0; /* ** The offset of the paRAM ID, from the starting of the paRAM set. */ static volatile unsigned short parOffRcvd = 0; /* ** The offset of the paRAM ID sent, from starting of the paRAM set. */ static volatile unsigned short parOffSent = 0; /* ** The offset of the paRAM ID to be sent next, from starting of the paRAM set. */ static volatile unsigned short parOffTxToSend = 0; /* ** The transmit buffer which was sent last. */ static volatile unsigned int lastSentTxBuf = NUM_BUF - 1; /* Array of receive buffer pointers */ static unsigned int const rxBufPtr[NUM_BUF] = { (unsigned int) rxBuf0, (unsigned int) rxBuf1, (unsigned int) rxBuf2 }; /* Array of transmit buffer pointers */ static unsigned int const txBufPtr[NUM_BUF] = { (unsigned int) txBuf0, (unsigned int) txBuf1, (unsigned int) txBuf2 }; /* ** Default paRAM for Transmit section. This will be transmitting from ** a loop buffer. */ static struct EDMA3CCPaRAMEntry const txDefaultPar = { (unsigned int)(EDMA3CC_OPT_DAM | (0x02 << 8u)), /* Opt field */ (unsigned int)loopBuf, /* source address */ (unsigned short)(BYTES_PER_SAMPLE), /* aCnt */ (unsigned short)(NUM_SAMPLES_LOOP_BUF), /* bCnt */ (unsigned int) SOC_MCASP_0_DATA_REGS, /* dest address */ (short) (BYTES_PER_SAMPLE), /* source bIdx */ (short)(0), /* dest bIdx */ (unsigned short)(PAR_TX_START * SIZE_PARAMSET), /* link address */ (unsigned short)(0), /* bCnt reload value */ (short)(0), /* source cIdx */ (short)(0), /* dest cIdx */ (unsigned short)1 /* cCnt */ }; /* ** Default paRAM for Receive section. */ static struct EDMA3CCPaRAMEntry const rxDefaultPar = { (unsigned int)(EDMA3CC_OPT_SAM | (0x02 << 8u)), /* Opt field */ (unsigned int)SOC_MCASP_0_DATA_REGS, /* source address */ (unsigned short)(BYTES_PER_SAMPLE), /* aCnt */ (unsigned short)(1), /* bCnt */ (unsigned int)rxBuf0, /* dest address */ (short) (0), /* source bIdx */ (short)(BYTES_PER_SAMPLE), /* dest bIdx */ (unsigned short)(PAR_RX_START * SIZE_PARAMSET), /* link address */ (unsigned short)(0), /* bCnt reload value */ (short)(0), /* source cIdx */ (short)(0), /* dest cIdx */ (unsigned short)1 /* cCnt */ }; /****************************************************************************/ /* 函数声明 */ /****************************************************************************/ static void ParamTxLoopJobSet(unsigned short parId); static void I2SDMAParamInit(void); static void AIC31I2SConfigure(void); static void McASPI2SConfigure(void); static void EDMA3IntSetup(void); static void McASPErrorIntSetup(void); static void I2SDataTxRxActivate(void); void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples, unsigned short parId, unsigned short linkPar); static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId, unsigned short parLink); static void McASPRxDMAComplHandler(void); static void McASPTxDMAComplHandler(void); static void EDMA3CCComplIsr(void); static void McASPErrorIsr(void); /****************************************************************************/ /* 主函数 */ /****************************************************************************/ int main(void) { unsigned short parToSend; unsigned short parToLink; UARTStdioInit(); UARTPuts("\r\n ============Test Start===========.\r\n", -1); UARTPuts("Welcome to StarterWare Audio_MIC_In Demo application.\r\n\r\n", -1); UARTPuts("This application loops back the input at MIC_IN of the EVM to the LINE_OUT of the EVM\r\n\r\n", -1); /* Set up pin mux for I2C module 0 */ I2CPinMuxSetup(0); McASPPinMuxSetup(); /* Power up the McASP module */ PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_MCASP0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE); /* Power up EDMA3CC_0 and EDMA3TC_0 */ PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE); PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON, PSC_MDCTL_NEXT_ENABLE); #ifdef _TMS320C6X // Initialize the DSP interrupt controller IntDSPINTCInit(); #else /* Initialize the ARM Interrupt Controller.*/ IntAINTCInit(); #endif /* Initialize the I2C 0 interface for the codec AIC31 */ I2CCodecIfInit(SOC_I2C_0_REGS, INT_CHANNEL_I2C, I2C_SLAVE_CODEC_AIC31); EDMA3Init(SOC_EDMA30CC_0_REGS, 0); EDMA3IntSetup(); McASPErrorIntSetup(); #ifdef _TMS320C6X IntGlobalEnable(); #else /* Enable the interrupts generation at global level */ IntMasterIRQEnable(); IntGlobalEnable(); IntIRQEnable(); #endif /* ** Request EDMA channels. Channel 0 is used for reception and ** Channel 1 is used for transmission */ EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA, EDMA3_CHA_MCASP0_TX, EDMA3_CHA_MCASP0_TX, 0); EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA, EDMA3_CHA_MCASP0_RX, EDMA3_CHA_MCASP0_RX, 0); /* Initialize the DMA parameters */ I2SDMAParamInit(); /* Configure the Codec for I2S mode */ AIC31I2SConfigure(); /* Configure the McASP for I2S */ McASPI2SConfigure(); /* Activate the audio transmission and reception */ I2SDataTxRxActivate(); /* ** Looop forever. if a new buffer is received, the lastFullRxBuf will be ** updated in the rx completion ISR. if it is not the lastSentTxBuf, ** buffer is to be sent. This has to be mapped to proper paRAM set. */ while(1) { if(lastFullRxBuf != lastSentTxBuf) { /* ** Start the transmission from the link paramset. The param set ** 1 will be linked to param set at PAR_TX_START. So do not ** update paRAM set1. */ parToSend = PAR_TX_START + (parOffTxToSend % NUM_PAR); parOffTxToSend = (parOffTxToSend + 1) % NUM_PAR; parToLink = PAR_TX_START + parOffTxToSend; lastSentTxBuf = (lastSentTxBuf + 1) % NUM_BUF; /* Copy the buffer */ memcpy((void *)txBufPtr[lastSentTxBuf], (void *)rxBufPtr[lastFullRxBuf], AUDIO_BUF_SIZE); /* ** Send the buffer by setting the DMA params accordingly. ** Here the buffer to send and number of samples are passed as ** parameters. This is important, if only transmit section ** is to be used. */ BufferTxDMAActivate(lastSentTxBuf, NUM_SAMPLES_PER_AUDIO_BUF, (unsigned short)parToSend, (unsigned short)parToLink); } } } /* ** Assigns loop job for a parameter set */ static void ParamTxLoopJobSet(unsigned short parId) { EDMA3CCPaRAMEntry paramSet; memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET - 2); /* link the paRAM to itself */ paramSet.linkAddr = parId * SIZE_PARAMSET; EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, &paramSet); } /* ** Initializes the DMA parameters. ** The RX basic paRAM set(channel) is 0 and TX basic paRAM set (channel) is 1. ** ** The RX paRAM set 0 will be initialized to receive data in the rx buffer 0. ** The transfer completion interrupt will not be enabled for paRAM set 0; ** paRAM set 0 will be linked to linked paRAM set starting (PAR_RX_START) of RX. ** and further reception only happens via linked paRAM set. ** For example, if the PAR_RX_START value is 40, and the number of paRAMS is 2, ** reception paRAM set linking will be initialized as 0-->40-->41-->40 ** ** The TX paRAM sets will be initialized to transmit from the loop buffer. ** The size of the loop buffer can be configured. ** The transfer completion interrupt will not be enabled for paRAM set 1; ** paRAM set 1 will be linked to linked paRAM set starting (PAR_TX_START) of TX. ** All other paRAM sets will be linked to itself. ** and further transmission only happens via linked paRAM set. ** For example, if the PAR_RX_START value is 42, and the number of paRAMS is 2, ** So transmission paRAM set linking will be initialized as 1-->42-->42, 43->43. */ static void I2SDMAParamInit(void) { EDMA3CCPaRAMEntry paramSet; int idx; /* Initialize the 0th paRAM set for receive */ memcpy(&paramSet, &rxDefaultPar, SIZE_PARAMSET - 2); EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX, &paramSet); /* further paramsets, enable interrupt */ paramSet.opt |= RX_DMA_INT_ENABLE; for(idx = 0 ; idx < NUM_PAR; idx++) { paramSet.destAddr = rxBufPtr[idx]; paramSet.linkAddr = (PAR_RX_START + ((idx + 1) % NUM_PAR)) * (SIZE_PARAMSET); paramSet.bCnt = NUM_SAMPLES_PER_AUDIO_BUF; /* ** for the first linked paRAM set, start receiving the second ** sample only since the first sample is already received in ** rx buffer 0 itself. */ if( 0 == idx) { paramSet.destAddr += BYTES_PER_SAMPLE; paramSet.bCnt -= BYTES_PER_SAMPLE; } EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, (PAR_RX_START + idx), &paramSet); } /* Initialize the required variables for reception */ nxtBufToRcv = idx % NUM_BUF; lastFullRxBuf = NUM_BUF - 1; parOffRcvd = 0; /* Initialize the 1st paRAM set for transmit */ memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET); EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX, &paramSet); /* rest of the params, enable loop job */ for(idx = 0 ; idx < NUM_PAR; idx++) { ParamTxLoopJobSet(PAR_TX_START + idx); } /* Initialize the variables for transmit */ parOffSent = 0; lastSentTxBuf = NUM_BUF - 1; } /* ** Function to configure the codec for I2S mode */ static void AIC31I2SConfigure(void) { volatile unsigned int delay = 0xFFF; AIC31Reset(SOC_I2C_0_REGS); while(delay--); /* Configure the data format and sampling rate */ AIC31DataConfig(SOC_I2C_0_REGS, AIC31_DATATYPE_I2S, SLOT_SIZE, 0); AIC31SampleRateConfig(SOC_I2C_0_REGS, AIC31_MODE_BOTH, SAMPLING_RATE); /* Initialize both ADC and DAC */ AIC31ADCInit(SOC_I2C_0_REGS); AIC31DACInit(SOC_I2C_0_REGS); } /* ** Configures the McASP Transmit Section in I2S mode. */ static void McASPI2SConfigure(void) { McASPRxReset(SOC_MCASP_0_CTRL_REGS); McASPTxReset(SOC_MCASP_0_CTRL_REGS); /* Enable the FIFOs for DMA transfer */ McASPReadFifoEnable(SOC_MCASP_0_FIFO_REGS, 1, 1); McASPWriteFifoEnable(SOC_MCASP_0_FIFO_REGS, 1, 1); /* Set I2S format in the transmitter/receiver format units */ McASPRxFmtI2SSet(SOC_MCASP_0_CTRL_REGS, WORD_SIZE, SLOT_SIZE, MCASP_RX_MODE_DMA); McASPTxFmtI2SSet(SOC_MCASP_0_CTRL_REGS, WORD_SIZE, SLOT_SIZE, MCASP_TX_MODE_DMA); /* Configure the frame sync. I2S shall work in TDM format with 2 slots */ McASPRxFrameSyncCfg(SOC_MCASP_0_CTRL_REGS, 2, MCASP_RX_FS_WIDTH_WORD, MCASP_RX_FS_EXT_BEGIN_ON_FALL_EDGE); McASPTxFrameSyncCfg(SOC_MCASP_0_CTRL_REGS, 2, MCASP_TX_FS_WIDTH_WORD, MCASP_TX_FS_EXT_BEGIN_ON_RIS_EDGE); /* configure the clock for receiver */ McASPRxClkCfg(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_EXTERNAL, 0, 0); McASPRxClkPolaritySet(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_POL_RIS_EDGE); McASPRxClkCheckConfig(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLKCHCK_DIV32, 0x00, 0xFF); /* configure the clock for transmitter */ McASPTxClkCfg(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_EXTERNAL, 0, 0); McASPTxClkPolaritySet(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_POL_FALL_EDGE); McASPTxClkCheckConfig(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLKCHCK_DIV32, 0x00, 0xFF); /* Enable synchronization of RX and TX sections */ McASPTxRxClkSyncEnable(SOC_MCASP_0_CTRL_REGS); /* Enable the transmitter/receiver slots. I2S uses 2 slots */ McASPRxTimeSlotSet(SOC_MCASP_0_CTRL_REGS, I2S_SLOTS); McASPTxTimeSlotSet(SOC_MCASP_0_CTRL_REGS, I2S_SLOTS); /* ** Set the serializers, Currently only one serializer is set as ** transmitter and one serializer as receiver. */ McASPSerializerRxSet(SOC_MCASP_0_CTRL_REGS, MCASP_XSER_RX); McASPSerializerTxSet(SOC_MCASP_0_CTRL_REGS, MCASP_XSER_TX); /* ** Configure the McASP pins ** Input - Frame Sync, Clock and Serializer Rx ** Output - Serializer Tx is connected to the input of the codec */ McASPPinMcASPSet(SOC_MCASP_0_CTRL_REGS, 0xFFFFFFFF); McASPPinDirOutputSet(SOC_MCASP_0_CTRL_REGS,MCASP_PIN_AXR(MCASP_XSER_TX)); McASPPinDirInputSet(SOC_MCASP_0_CTRL_REGS, MCASP_PIN_AFSX | MCASP_PIN_ACLKX | MCASP_PIN_AHCLKX | MCASP_PIN_AXR(MCASP_XSER_RX)); /* Enable error interrupts for McASP */ McASPTxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_TX_DMAERROR | MCASP_TX_CLKFAIL | MCASP_TX_SYNCERROR | MCASP_TX_UNDERRUN); McASPRxIntEnable(SOC_MCASP_0_CTRL_REGS, MCASP_RX_DMAERROR | MCASP_RX_CLKFAIL | MCASP_RX_SYNCERROR | MCASP_RX_OVERRUN); } /* ** Sets up the interrupts for EDMA in AINTC */ static void EDMA3IntSetup(void) { #ifdef _TMS320C6X IntRegister(C674X_MASK_INT5, EDMA3CCComplIsr); IntEventMap(C674X_MASK_INT5, SYS_INT_EDMA3_0_CC0_INT1); IntEnable(C674X_MASK_INT5); #else IntRegister(SYS_INT_CCINT0, EDMA3CCComplIsr); IntChannelSet(SYS_INT_CCINT0, INT_CHANNEL_EDMACC); IntSystemEnable(SYS_INT_CCINT0); #endif } /* ** Sets up the error interrupts for McASP in AINTC */ static void McASPErrorIntSetup(void) { #ifdef _TMS320C6X IntRegister(C674X_MASK_INT6, McASPErrorIsr); IntEventMap(C674X_MASK_INT6, SYS_INT_MCASP0_INT); IntEnable(C674X_MASK_INT6); #else /* Register the error ISR for McASP */ IntRegister(SYS_INT_MCASPINT, McASPErrorIsr); IntChannelSet(SYS_INT_MCASPINT, INT_CHANNEL_MCASP); IntSystemEnable(SYS_INT_MCASPINT); #endif } /* ** Activates the data transmission/reception ** The DMA parameters shall be ready before calling this function. */ static void I2SDataTxRxActivate(void) { /* Start the clocks */ McASPRxClkStart(SOC_MCASP_0_CTRL_REGS, MCASP_RX_CLK_EXTERNAL); McASPTxClkStart(SOC_MCASP_0_CTRL_REGS, MCASP_TX_CLK_EXTERNAL); /* Enable EDMA for the transfer */ EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX, EDMA3_TRIG_MODE_EVENT); EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX, EDMA3_TRIG_MODE_EVENT); /* Activate the serializers */ McASPRxSerActivate(SOC_MCASP_0_CTRL_REGS); McASPTxSerActivate(SOC_MCASP_0_CTRL_REGS); /* make sure that the XDATA bit is cleared to zero */ while(McASPTxStatusGet(SOC_MCASP_0_CTRL_REGS) & MCASP_TX_STAT_DATAREADY); /* Activate the state machines */ McASPRxEnable(SOC_MCASP_0_CTRL_REGS); McASPTxEnable(SOC_MCASP_0_CTRL_REGS); } /* ** Activates the DMA transfer for a parameterset from the given buffer. */ void BufferTxDMAActivate(unsigned int txBuf, unsigned short numSamples, unsigned short parId, unsigned short linkPar) { EDMA3CCPaRAMEntry paramSet; /* Copy the default paramset */ memcpy(&paramSet, &txDefaultPar, SIZE_PARAMSET - 2); /* Enable completion interrupt */ paramSet.opt |= TX_DMA_INT_ENABLE; paramSet.srcAddr = txBufPtr[txBuf]; paramSet.linkAddr = linkPar * SIZE_PARAMSET; paramSet.bCnt = numSamples; EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, &paramSet); } /* ** Activates the DMA transfer for a parameter set from the given buffer. */ static void BufferRxDMAActivate(unsigned int rxBuf, unsigned short parId, unsigned short parLink) { EDMA3CCPaRAMEntry paramSet; /* Copy the default paramset */ memcpy(&paramSet, &rxDefaultPar, SIZE_PARAMSET - 2); /* Enable completion interrupt */ paramSet.opt |= RX_DMA_INT_ENABLE; paramSet.destAddr = rxBufPtr[rxBuf]; paramSet.bCnt = NUM_SAMPLES_PER_AUDIO_BUF; paramSet.linkAddr = parLink * SIZE_PARAMSET ; EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, parId, &paramSet); } /* ** This function will be called once receive DMA is completed */ static void McASPRxDMAComplHandler(void) { unsigned short nxtParToUpdate; /* ** Update lastFullRxBuf to indicate a new buffer reception ** is completed. */ lastFullRxBuf = (lastFullRxBuf + 1) % NUM_BUF; nxtParToUpdate = PAR_RX_START + parOffRcvd; parOffRcvd = (parOffRcvd + 1) % NUM_PAR; /* ** Update the DMA parameters for the received buffer to receive ** further data in proper buffer */ BufferRxDMAActivate(nxtBufToRcv, nxtParToUpdate, PAR_RX_START + parOffRcvd); /* update the next buffer to receive data */ nxtBufToRcv = (nxtBufToRcv + 1) % NUM_BUF; } /* ** This function will be called once transmit DMA is completed */ static void McASPTxDMAComplHandler(void) { ParamTxLoopJobSet((unsigned short)(PAR_TX_START + parOffSent)); parOffSent = (parOffSent + 1) % NUM_PAR; } /* ** EDMA transfer completion ISR */ static void EDMA3CCComplIsr(void) { #ifdef _TMS320C6X IntEventClear(SYS_INT_EDMA3_0_CC0_INT1); #else IntSystemStatusClear(SYS_INT_CCINT0); #endif /* Check if receive DMA completed */ if(EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS) & (1 << EDMA3_CHA_MCASP0_RX)) { /* Clear the interrupt status for the 0th channel */ EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_RX); McASPRxDMAComplHandler(); } /* Check if transmit DMA completed */ if(EDMA3GetIntrStatus(SOC_EDMA30CC_0_REGS) & (1 << EDMA3_CHA_MCASP0_TX)) { /* Clear the interrupt status for the first channel */ EDMA3ClrIntr(SOC_EDMA30CC_0_REGS, EDMA3_CHA_MCASP0_TX); McASPTxDMAComplHandler(); } } /* ** Error ISR for McASP */ static void McASPErrorIsr(void) { #ifdef _TMS320C6X IntEventClear(SYS_INT_MCASP0_INT); #else IntSystemStatusClear(SYS_INT_MCASPINT); #endif ; /* Perform any error handling here.*/ } /***************************** End Of File ***********************************/ 将以上代码和以下代码合在一起:#include "math.h" #include "mathlib.h" #include "dsplib.h" #define PI 3.1415926535 #define F_TOL (1e-06) #define Tn 1024 #define Fs 48000.0 #define N 132 // 滤波器阶数(偶数) #define FilterCount 5 const float F1s[FilterCount] = {20.0, 400.0, 1200.0, 4000.0, 13000.0}; const float F2s[FilterCount] = {400.0, 1200.0, 4000.0, 13000.0, 20000.0}; #pragma DATA_ALIGN(FIR_In, 8); float FIR_In[Tn]; #pragma DATA_ALIGN(FIR_Outs, 8); float FIR_Outs[FilterCount][Tn]; #pragma DATA_ALIGN(FIR_CombinedOut, 8); float FIR_CombinedOut[Tn]; #pragma DATA_ALIGN(Bs, 8); float Bs[FilterCount][N]; void FIRTest(void); void design_blackman_bandpass_fir(float *h, int n, float f1, float f2, float fs); void blackman_window(float *w, int n); void normalize_filter_response(float *h, int n, float f1, float f2, float fs); int main(void) { int i; // 声明循环变量 for (i = 0; i < FilterCount; i++) { design_blackman_bandpass_fir(Bs[i], N, F1s[i], F2s[i], Fs); } FIRTest(); return 0; } void blackman_window(float *w, int n) { int i; // 声明循环变量 for (i = 0; i < n; i++) { w[i] = 0.42f - 0.5f * cosf(2.0f * PI * i / (n - 1)) + 0.08f * cosf(4.0f * PI * i / (n - 1)); } } void normalize_filter_response(float *h, int n, float f1, float f2, float fs) { float center_freq = (f1 + f2) / 2.0f; float omega = 2.0f * PI * center_freq / fs; float real_gain = 0.0f; int i; // 声明循环变量 for (i = 0; i < n; i++) { real_gain += h[i] * cosf(omega * (i - (n-1)/2.0f)); } if (fabsf(real_gain) > F_TOL) { for (i = 0; i < n; i++) { h[i] /= real_gain; } } } void design_blackman_bandpass_fir(float *h, int n, float f1, float f2, float fs) { float w[N]; float fc1 = f1 / fs; float fc2 = f2 / fs; int i; // 声明循环变量 blackman_window(w, n); for (i = 0; i < n; i++) { float m = i - (n - 1)/2.0f; h[i] = (fabsf(m) < F_TOL) ? 2.0f * (fc2 - fc1) : (sinf(2.0f * PI * fc2 * m) - sinf(2.0f * PI * fc1 * m)) / (PI * m); h[i] *= w[i]; } normalize_filter_response(h, n, f1, f2, fs); } void FIRTest(void) { int i, j; // 声明循环变量 // 生成测试信号 - 每个频段一个测试频率 for (i = 0; i < Tn; i++) { float t = (float)i / Fs; FIR_In[i] = 5.0f * sinf(2.0f * PI * 10.0f * t) + 5.0f * sinf(2.0f * PI * 15000.0f * t)+ 5.0f * sinf(2.0f * PI * 25000.0f * t); } // 初始化并处理滤波器输出 for (i = 0; i < Tn; i++) { FIR_CombinedOut[i] = 0.0f; } for (j = 0; j < FilterCount; j++) { DSPF_sp_fir_r2(FIR_In, Bs[j], FIR_Outs[j], N, Tn); // 累加各滤波器输出 for (i = 0; i < Tn; i++) { FIR_CombinedOut[i] += FIR_Outs[j][i]; } } } 将测试信号去掉,合成后的代码输入就是音频输入,输出就是音频输出,滤波器来处理数据
05-13
/*-------------------------------------------\ * SC8F072 SOP16 * ---------------- * ------------|1(VDD) (GND)16|------------- USB_5V* ------------|2(RB0) (RA0)15|-------------ADC * ------------|3(RB1) (RA1)14|-------------TP4056_7 ------------|4(RB2) (RA2)13|------------- S1 ------------|5(RB3) (RA3)12|-------------LED1 S2 ------------|6(RB4) (RA4)11|-------------LED2 MD_PMW* ------------|7(RB5) (RA5)10|-------------LED3 LED5* ------------|8(RB6) (RB7)9|--------------LED4 * ---------------- -------------------------------------------*/ #include <sc.h> //芯片头文件,会根据工程选项自动寻找对应型号头文件 #define _XTAL_FREQ 16000000 //16MHz,使用内置延时函数必须定义主频, #define SEG1_IN TRISA3 = 1 #define SEG1_LOW RA3 = 0;TRISA3 = 0 #define SEG1_HIGH RA3 = 1;TRISA3 = 0 #define SEG2_IN TRISA4 = 1 #define SEG2_LOW RA4 = 0;TRISA4 = 0 #define SEG2_HIGH RA4 = 1;TRISA4 = 0 #define SEG3_IN TRISA5 = 1 #define SEG3_LOW RA5 = 0;TRISA5 = 0 #define SEG3_HIGH RA5 = 1;TRISA5 = 0 #define SEG4_IN TRISB7 = 1 #define SEG4_LOW RB7 = 0;TRISB7 = 0 #define SEG4_HIGH RB7 = 1;TRISB7 = 0 #define SEG5_IN TRISB6 = 1 #define SEG5_LOW RB6 = 0;TRISB6 = 0 #define SEG5_HIGH RB6 = 1;TRISB6 = 0 #define KEY1 RB3 #define KEY2 RB4 #define USB_5V RB0 #define TP4056_7 RA1 // 0 1 2 3 4 5 6 7 8 9 关 H F U - const unsigned char Look_Table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x76,0x71,0x3e,0x40}; volatile bit run_10ms_flag; //10MS定时标志位 volatile unsigned char t_100us_10ms_cnt; volatile unsigned char t_10ms_cnt; volatile unsigned char sleep_10ms_cnt; volatile bit on_off_flag; volatile unsigned char mode; volatile bit k1_short_flag; volatile bit k1_short_en_flag; volatile unsigned char k1_10ms_yes_cnt; volatile unsigned char k1_10ms_no_cnt; volatile bit k2_short_flag; volatile bit k2_short_en_flag; volatile unsigned char k2_10ms_yes_cnt; volatile unsigned char k2_10ms_no_cnt; volatile unsigned char led_ff; volatile unsigned char led_dd; volatile unsigned char led_cnt; volatile unsigned char led_dang; volatile unsigned char pwm_data; volatile unsigned char pwm_data_10ms_cnt; volatile unsigned char pwm_data_run_10ms_cnt; volatile unsigned char data1; volatile unsigned char data2; volatile unsigned char led_shan_num_cnt; volatile unsigned char led_shan_10ms_cnt; volatile bit usb_5v_flag; volatile unsigned char usb_5v_10ms_no_cnt; volatile unsigned char usb_5v_10ms_yes_cnt; volatile bit fu_flag; volatile unsigned char fu_10ms_cnt; volatile unsigned int adresult; volatile unsigned char gl_10ms_cnt; volatile bit one_flag; volatile unsigned char battery_percent; //电池电量 volatile unsigned char battery_percent_temp; //电池电量临时 volatile unsigned char battery_percent_10ms_cnt; volatile unsigned char battery_percent_1s_cnt; volatile unsigned int data; volatile unsigned char bat_num; volatile unsigned int bat_adc_data; volatile unsigned int bat_max; volatile unsigned int bat_min; volatile unsigned char l_3v_10ms_cnt; volatile bit low_power_off_flag; volatile unsigned int low_power_shan_10ms_cnt; volatile unsigned int xs_10ms_cnt; volatile unsigned int timeing_10ms_cnt; void My_Ram_Init() { on_off_flag = 0; mode = 1; data = 0; bat_num = 0; bat_adc_data = 0; bat_max = 0; bat_min = 5000; } void Init_System()// 8/16M { asm("nop"); asm("clrwdt"); INTCON = 0; //系统初始化 OSCCON = 0x72; //16MHZ,内部振荡器用作系统时钟,CONFIG关闭WDT时必需软件打开WDT OPTION_REG = 0x00; //配置TIMER0时间,00为2分频 asm("clrwdt"); WPUA = 0B00000010; //初始化上拉 WPDA = 0B00000000; //初始化下拉 TRISA = 0B00000011; //初始化IO状态 PORTA = 0B00000000; //初始化输出 WPUB = 0B00011000; //初始化上拉 WPDB = 0B00000000; //初始化下拉 TRISB = 0B00011001; //初始化IO状态 PORTB = 0B00000000; //初始化输出 } void Time2_Init() //100us { PR2 = 99; //设定Timer初始值, TMR2IF = 0; TMR2IE = 1; //使能Timer2溢出中断 T2CON = 0B00000101; //开启Timer2,预分频为1:4,后分频为1:1,则定时时间为(99+1)*4*(4/16M)=100us //timer2的时钟源为OSCCON配置的系统时钟/2 INTCON = 0XC0; //开启总中断及外设中断 } #define FAN_FF 250 //64分频 1K左右 void Pwm_Init() //220K { //以下是对PWM功能初始化 /************PWMCON1定义************************** Bit7~6 PWMIO_SEL[1:0]: PWM IO选择。 11= PWM分配在A组,PWM0-RA0,PWM1-RA1,PWM2-RA2,PWM3-RA3,PWM4-RA4 10= PWM分配在B组,PWM0-RA0,PWM1-RA1,PWM2-RA2,PWM3-RB2,PWM4-RB1 01= PWM分配在C组,PWM0-RA5,PWM1-RB7,PWM2-RB6,PWM3-RB5,PWM4-RB4 00= PWM分配在D组,PWM0-RB0,PWM1-RB1,PWM2-RB3,PWM3-RB4,PWM4-RB2 Bit5 PWM2DTEN: PWM2死区使能位。 1= 使能PWM2死区功能,PWM2和PWM3组成一对互补输出。 0= 禁止PWM2死区功能。 Bit4 PWM0DTEN: PWM0死区使能位。 1= 使能PWM0死区功能,PWM0和PWM1组成一对互补输出。 0= 禁止PWM0死区功能。 Bit3~Bit2 未用。 Bit1~Bit0 DT_DIV[1:0] 死区时钟源分频。 11= FOSC/8 10= FOSC/4 01= FOSC/2 00= FOSC/1 **********************************************************************/ TRISB5 = 1; PWMCON1 = 0B01000000; //PWM选择C组 PWMTL = FAN_FF; //PWM 周期=[PWMT+1]*Tosc*(CLKDIV 分频值) PWMT4L = FAN_FF; PWMTH = 0; //周期选择为0FF,则周期为(255+1)*1/8M,周期的时钟分频在PWMCON0选择 //PWM4周期选择为03FF PWMD0L = 0; //脉冲宽度 = (PWMDx[9:0]+1)*TOSC*(CLKDIV 分频值) //必须注意根据公式,即使占空比设为0仍有脉冲输出,如要输出低电平 //需要关闭PWMEN,然后设为输出低 PWMD1L = 0; //互补模式,PWM1的占空比与PWM0互补,和设置值无关 PWMD01H = 0; //配置PWM1,PWM2的占空比,该值不能超过周期,否者为100%输出 PWM01DT = 0; //死区设为2uS,计算为(3+1)*1/8M*4 //死区1的占空比以PWM0设置的占空比为基准 PWMD2L = 0; //PWM2 占空比低位寄存器 该值不能超过周期,否者为100%输出 PWMD3L = 0; //PWM3 占空比低位寄存器 ,互补以PWM0占空比为准 PWMD23H = 0; //PWM2 和 PWM3 占空比高位寄存器 PWMD01H,该值不能超过周期,否者为100%输出 PWMD4L = 0; //PWM4 占空比低位寄存器,PWM4占空比高位在PWMTH的Bit4~5 /***************PWMCON0************************************* Bit7~Bit5 CLKDIV[2:0]: PWM时钟分频。 111= FOSC/128 110= FOSC/64 101= FOSC/32 100= FOSC/16 011= FOSC/8 010= FOSC/4 001= FOSC/2 000= FOSC/1 Bit4~Bit0 PWMxEN: PWMx使能位。 1= 使能PWMx。 0= 禁止PWMx。 ******************************************************************/ PWMCON0 = 0b11000000; //64分频 TRISB5 = 0; } void Pwm_Md(unsigned char dd) { if(dd) { PWMD3L = dd; PWM3EN = 1; } else { PWMD3L = 0; PWM3EN = 0; RB5 = 0; } } void Led_Data() { unsigned char data1_temp,data2_temp; data1_temp = 0; data2_temp = 0; if(xs_10ms_cnt)xs_10ms_cnt--; if(low_power_shan_10ms_cnt)low_power_shan_10ms_cnt--; if(xs_10ms_cnt || usb_5v_flag || on_off_flag || low_power_shan_10ms_cnt) { if(low_power_shan_10ms_cnt) { if(low_power_shan_10ms_cnt > 450)data2_temp |= 0x07; else if(low_power_shan_10ms_cnt > 400)data2_temp |= 0x00; else if(low_power_shan_10ms_cnt > 350)data2_temp |= 0x07; else if(low_power_shan_10ms_cnt > 300)data2_temp |= 0x00; else if(low_power_shan_10ms_cnt > 250)data2_temp |= 0x07; else if(low_power_shan_10ms_cnt > 200)data2_temp |= 0x00; else if(low_power_shan_10ms_cnt > 150)data2_temp |= 0x07; else if(low_power_shan_10ms_cnt > 100)data2_temp |= 0x00; else if(low_power_shan_10ms_cnt > 50)data2_temp |= 0x07; else data2_temp |= 0x00; data2_temp |= 0xf0; } else if(usb_5v_flag == 1) //插入充电 { led_shan_10ms_cnt++; if(led_shan_10ms_cnt > 50) //0.5秒闪 { led_shan_10ms_cnt = 0; led_shan_num_cnt++; if(led_shan_num_cnt > 4)led_shan_num_cnt = battery_percent_temp; if(led_shan_num_cnt == 0)led_shan_num_cnt = 1; } if(fu_flag == 0) //充电中 { if(led_shan_num_cnt == 1)data2_temp |= 0x00; else if(led_shan_num_cnt == 2)data2_temp |= 0x01; else if(led_shan_num_cnt == 3)data2_temp |= 0x03; else if(led_shan_num_cnt == 4)data2_temp |= 0x07; } else { data2_temp |= 0x07; } data2_temp |= 0xf0; } else { data1_temp = Look_Table[mode]; if(battery_percent_temp == 1)data2_temp |= 0x01; else if(battery_percent_temp == 2)data2_temp |= 0x03; else if(battery_percent_temp == 3)data2_temp |= 0x07; data2_temp |= 0xf0; } } data1 = data1_temp; data2 = data2_temp; } void Led_Scan() { if(on_off_flag || usb_5v_flag || xs_10ms_cnt || low_power_shan_10ms_cnt) { SEG1_IN; SEG2_IN; SEG3_IN; SEG4_IN; SEG5_IN; led_dang++; if(led_dang > 4)led_dang = 1; if(led_dang == 1) { if(data1 & 0x01) { SEG2_HIGH; //a1 } if(data1 & 0x02) { SEG3_HIGH; //b1 } if(data1 & 0x04) { SEG4_HIGH; //c1 } if(data1 & 0x08) { SEG5_HIGH; //d1 } SEG1_LOW; } else if(led_dang == 2) { if(data1 & 0x10) { SEG1_HIGH; //e1 } if(data1 & 0x20) { SEG3_HIGH; //f1 } if(data1 & 0x40) { SEG4_HIGH; //g1 } if(data2 & 0x80) { SEG5_HIGH; } SEG2_LOW; } else if(led_dang == 3) { if(data2 & 0x40) { SEG1_HIGH; } if(data2 & 0x20) { SEG2_HIGH; } if(data2 & 0x10) { SEG4_HIGH; } if(data2 & 0x04) { SEG5_HIGH; } SEG3_LOW; } else if(led_dang == 4) { if(data2 & 0x02) { SEG1_HIGH; } if(data2 & 0x01) { SEG2_HIGH; } SEG4_LOW; } } else { SEG1_LOW; SEG2_LOW; SEG3_LOW; SEG4_LOW; SEG5_LOW; } } /*********************************************************** 中断服务函数 函数名称:AD_Init() 函数功能:AD初始化处理函数 入口参数: 出口参数: 备 注:第一次打开AD允许位ADON,需延时20uS以上才能进入AD采样 如后继程序不关闭ADON,则不需要延时 ***********************************************************/ void AD_Init() { ANSEL0 = 0B00000001; //AN0 ANSEL1 = 0B00000000; // /*********** ADCON0 **************************** Bit7~Bit6 ADCS<1:0>: AD转换时钟选择位。 00= F HSI /16 01= F HSI /32 10= F HSI /64 11= F HSI /128 Bit5~Bit2 CHS<3:0>: 模拟通道选择位。与ADCON1寄存器CHS4组合CHS<3:0> CHS<4:0>: 00000= AN0 00001= AN1 00010= AN2 00011= AN3 00100= AN4 00101= AN5 00110= 保留 00111= 保留 01000= AN8 … 01101= AN13 01110= AN14 01111= AN15 11111= 1.2V(固定参考电压) 其他= 保留 Bit1 GO/DONE: AD转换状态位。 1= AD转换正在进行。将该位置1启动AD转换。当AD转换完成以后,该位由硬件自动清零。 当GO/DONE位从1变0或ADIF从0变1时,需至少等待两个TAD时间,才能再次启动AD转换。 0= AD转换完成/或不在进行中。 Bit0 ADON: ADC使能位。 1= 使能ADC; 0= 禁止ADC,不消耗工作电流。 *********************************************/ ADCON0 = 0X41; //ADON开启,AD采样时间选为FSYS/16 /*********** ADCON1 **************************** Bit7 ADFM: AD转换结果格式选择位; 1= 右对齐; 0= 左对齐。 Bit6 CHS4: 通道选择位 Bit5~Bit3 未用 Bit2 LDO_EN: 内部参考电压使能位。 1= 使能ADC内部LDO参考电压; 当选择内部LDO作参考电压时,ADC最大有效精度为8位。 0= VDD作为ADC参考电压。 Bit1~Bit0 LDO_SEL<1:0>: 参考电压选择位 0X= 2.0V 10= 2.4V 11= 3.0V *********************************************/ ADCON1 = 0; } /********************************************************** 函数名称:AD_Sample 函数功能:AD检测 入口参数:adch - 检测通道 出口参数:无 备 注:采样通道需自行设置为输入口 采样10次,取中间八次的平均值为采样结果存于adresult中 adch 为输入AD通道 0-15,31 31 检测内部1.2V adldo =5,开启内部LDO 2V 作为ADC 参考 adldo =6,开启内部LDO 2.4V 作为ADC 参考 adldo =7,开启内部LDO 3V 作为ADC 参考 adldo =0,VDD 作为ADC 参考 AD转换结果左对齐 ADC参考电压从VDD切换到LDO时需要延时100us以上,才能进行AD转换 **********************************************************/ unsigned char ADC_Sample(unsigned char adch, unsigned char adldo) { volatile unsigned long adsum = 0; volatile unsigned int admin = 0, admax = 0; volatile unsigned int ad_temp = 0; if ((!LDO_EN) && (adldo & 0x04) ) { //如果AD参考从VDD换到内部LDO,需要延时100US以上 ADCON1 = adldo; //左对齐,AD值取12位 __delay_us(100); //IDE内置延时函数,延时100us } else ADCON1 = adldo; //如果ADCON1.7(ADFM)=1为右对齐,,AD值取10位 if(adch & 0x10) { CHS4 = 1; adch &= 0x0f; } unsigned char i = 0; for (i = 0; i < 10; i++) { ADCON0 = (unsigned char)(0X41 | (adch << 2)); //16分频,如果主频为16M,则必须选16分频或以上 asm("nop"); asm("nop"); asm("nop"); asm("nop"); //选择通道后需延时1uS以上 GODONE = 1; //开始转换 unsigned int j = 0; while (GODONE) { __delay_us(2); //延时2us(编译器内置函数) if (0 == (--j)) //延时0.5ms仍没有AD转换结束,跳出程序 return 0; } ad_temp = (unsigned int)((ADRESH << 4) + (ADRESL >> 4)); //计算12位AD值 if (0 == admax) { admax = ad_temp; admin = ad_temp; } else if (ad_temp > admax) admax = ad_temp; //AD采样最大值 else if (ad_temp < admin) admin = ad_temp; //AD采样最小值 adsum += ad_temp; } adsum -= admax; if (adsum >= admin) adsum -= admin; else adsum = 0; adresult = adsum >> 3; //8次平均值作为最终结果 adsum = 0; admin = 0; admax = 0; return 0xA5; } void Bat_Read() //读电池电压 { ADC_Sample(31,0); // 1.2V基准, 左对齐,VDD作为参考电压 bat_adc_data += adresult; if(adresult > bat_max)bat_max = adresult; if(adresult < bat_min)bat_min = adresult; bat_num++; if(bat_num >= 10) { bat_adc_data = bat_adc_data - bat_max - bat_min; bat_adc_data = bat_adc_data >> 3; if(usb_5v_flag == 0) //放电中 { if(bat_adc_data <= 1293) //大于3.8 3格 { l_3v_10ms_cnt = 0; battery_percent = 3; } else if(bat_adc_data > 1585) //小于3.1V { l_3v_10ms_cnt++; if(l_3v_10ms_cnt > 4) { l_3v_10ms_cnt = 0; battery_percent_temp = 0; battery_percent = 0; } } else if(bat_adc_data < 1404) //大于3.5V 2格 { battery_percent = 2; } else //1格 { battery_percent = 1; } } else //充电中 { if(bat_adc_data < 1198) //大于4.1 3格 { battery_percent = 3; } else if(bat_adc_data < 1293) //大于3.8V 2格 { battery_percent = 2; } else if(bat_adc_data < 1404) //大于3.5V 1格 { battery_percent = 1; } else //0格 { battery_percent = 0; } } if(battery_percent > 3)battery_percent = 3; if(one_flag == 0) //首次上电 { battery_percent_temp = battery_percent; one_flag = 1; } if(battery_percent_temp == 0) //没有电了关机 { if(usb_5v_flag == 0 && low_power_off_flag == 0) { on_off_flag = 0; Pwm_Md(0); low_power_off_flag = 1; //低压关机标记 low_power_shan_10ms_cnt = 500; } } bat_num = 0; bat_adc_data = 0; bat_max = 0; bat_min = 5000; } } void Bat_Add_Sub() //电池电量加或减 { unsigned char time_temp; battery_percent_10ms_cnt++; if(battery_percent_10ms_cnt >= 100) //1s { battery_percent_10ms_cnt = 0; battery_percent_1s_cnt++; if(usb_5v_flag == 0) //没在充电 { time_temp = 3; if(battery_percent_1s_cnt > time_temp) { battery_percent_1s_cnt = 0; if(battery_percent_temp > battery_percent)battery_percent_temp--; } } else //充电中 { if(fu_flag == 0)time_temp = 60;//60秒 else time_temp = 10;//10秒 if(battery_percent_1s_cnt > time_temp) { battery_percent_1s_cnt = 0; if(fu_flag == 0) //没充满 { if(battery_percent_temp < battery_percent) { battery_percent_temp++; } } else { if(battery_percent_temp < 3) { battery_percent_temp++; } } } } } } void All_Mode() { if(mode == 1)pwm_data = 95; //38% else if(mode == 2)pwm_data = 100; //40% else if(mode == 3)pwm_data = 100; //40% else if(mode == 4)pwm_data = 102; //41% else if(mode == 5)pwm_data = 112; //45% else if(mode == 6)pwm_data = 117; //47% else if(mode == 7)pwm_data = 122; //49% else if(mode == 8)pwm_data = 122; //49% } void Key_Scan() { if(usb_5v_flag == 0) //不充电的时候按键才有作用 { if(KEY1 == 0) { k1_10ms_no_cnt = 0; k1_10ms_yes_cnt++; if(k1_10ms_yes_cnt > 2) { if(k1_short_flag == 0) { k1_short_flag = 1; k1_short_en_flag = 1; } } } else { k1_10ms_yes_cnt = 0; k1_10ms_no_cnt++; if(k1_10ms_no_cnt > 2) { k1_short_flag = 0; } } if(KEY2 == 0) { k2_10ms_no_cnt = 0; k2_10ms_yes_cnt++; if(k2_10ms_yes_cnt > 2) { if(k2_short_flag == 0) { k2_short_flag = 1; k2_short_en_flag = 1; } } } else { k2_10ms_yes_cnt = 0; k2_10ms_no_cnt++; if(k2_10ms_no_cnt > 2) { k2_short_flag = 0; } } } if(USB_5V == 1) { usb_5v_10ms_no_cnt = 0; usb_5v_10ms_yes_cnt++; if(usb_5v_10ms_yes_cnt > 5) { usb_5v_flag = 1; low_power_off_flag = 0; low_power_shan_10ms_cnt = 0; on_off_flag = 0; Pwm_Md(0); } } else { usb_5v_10ms_yes_cnt = 0; usb_5v_10ms_no_cnt++; if(usb_5v_10ms_no_cnt > 5) { usb_5v_flag = 0; fu_flag = 0; } } if(usb_5v_flag == 1) { if(TP4056_7 == 1) { fu_10ms_cnt++; if(fu_10ms_cnt > 200) { fu_10ms_cnt = 0; fu_flag = 1; } } else fu_10ms_cnt = 0; } } void Key_Service() { if(k1_short_en_flag == 1) //短按开关 { k1_short_en_flag = 0; if(low_power_off_flag == 1) //低压标记 { low_power_shan_10ms_cnt = 500; } else { if(on_off_flag == 0) { on_off_flag = 1; xs_10ms_cnt = 0; All_Mode(); } else { on_off_flag = 0; Pwm_Md(0); } } } if(k2_short_en_flag == 1) { k2_short_en_flag = 0; if(on_off_flag == 0 && low_power_shan_10ms_cnt == 0)xs_10ms_cnt = 400; //显示4秒 mode++; if(mode > 8)mode = 1; All_Mode(); } } void Sleep_Mode() { if(on_off_flag == 0 && USB_5V == 0 && KEY1 == 1 && KEY2 == 1 && xs_10ms_cnt == 0 && low_power_shan_10ms_cnt == 0) { sleep_10ms_cnt++; if(sleep_10ms_cnt > 200) { sleep_10ms_cnt = 0; INTCON = 0; OPTION_REG = 0; ANSEL0 = 0B00000000; ANSEL1 = 0B00000000; ADCON0 = 0; //关闭所有模块 ADCON1 = 0; PWMCON0 = 0; OSCCON = 0X70; //配置振荡为8M,关闭WDT,需注意芯片工程选项里WDT必须选为DISABLE,否则无法软件关掉WDT IOCA = 0B00000000; // IOCB = 0B00011001; //允许RB034的IO口电平变化中断 RAIE = 0; // PEIE = 0; //要用RORTA中断唤醒,则PEIE必须设为1 RBIE = 1; //允许PORTB电平变化中断 GIE = 0; //唤醒后执行SLEEP后程序; PORTA; //读PORTA值并锁存,用电平变化中断必须执行这一步 RAIF = 0; //清PORTA中断标志位 PORTB; //读PORTB值并锁存 RBIF = 0; //清PORTB中断标志位 asm("clrwdt"); asm("sleep"); //进入休眠模式 asm("nop"); asm("clrwdt"); IOCA = 0B00000000; IOCB = 0B00000000; RAIE = 0; PEIE = 0; RBIE = 0; OSCCON = 0X72; //配置振荡为8M,开WDT,需注意芯片工程选项里WDT必须选为DISABLE,否则无法软件关掉WDT asm("clrwdt"); if(RAIF) RAIF = 0; //清中断标志 if(RBIF) RBIF = 0; //清中断标志 AD_Init(); Pwm_Init(); Time2_Init(); //100us 16M } } else sleep_10ms_cnt = 0; } void Md_Fun() { unsigned char pwm_temp,add_time; if(on_off_flag == 1) { if(mode == 1) { add_time = 4; pwm_temp = 215; //86% } else if(mode == 2) { add_time = 16; pwm_temp = 130; //52% } else if(mode == 3) { add_time = 10; pwm_temp = 150; //60% } else if(mode == 4) { add_time = 7; pwm_temp = 170; //68% } else if(mode == 5) { add_time = 6; pwm_temp = 190; //76% } else if(mode == 6) { add_time = 5; pwm_temp = 220; //88% } else if(mode == 7) { add_time = 4; pwm_temp = 235; //94% } else if(mode == 8) { add_time = 4; pwm_temp = 250; //100% } pwm_data_10ms_cnt++; if(pwm_data_10ms_cnt >= add_time) { pwm_data_10ms_cnt = 0; if(pwm_data < pwm_temp)pwm_data++; } pwm_data_run_10ms_cnt++; if(pwm_data_run_10ms_cnt >= 100)pwm_data_run_10ms_cnt = 0; if((mode == 1) && (pwm_data_run_10ms_cnt > 50)) { Pwm_Md(0); } else { Pwm_Md(pwm_data); } timeing_10ms_cnt++; if(timeing_10ms_cnt >= 9000) //开90s关机 { on_off_flag = 0; } ADC_Sample(0,5); //过流保护 if(adresult > 389) //大于0.19V (大约3.8A) { gl_10ms_cnt++; if(gl_10ms_cnt > 60) { gl_10ms_cnt = 0; on_off_flag = 0; Pwm_Md(0); } } else { if(gl_10ms_cnt)gl_10ms_cnt--; } } else { Pwm_Md(0); timeing_10ms_cnt = 0; } } void main() { Init_System(); My_Ram_Init(); AD_Init(); Pwm_Init(); Time2_Init(); while(1) { asm("clrwdt"); if(run_10ms_flag == 1) //10ms { run_10ms_flag = 0; Key_Scan(); Key_Service(); Md_Fun(); Led_Data(); Bat_Read(); //读电池电压 Bat_Add_Sub(); //电池电量加或减 Sleep_Mode(); //进低功耗 } } } void interrupt Timer_Isr() { if(TMR2IF) { TMR2IF = 0; //清中断标志位 t_100us_10ms_cnt++; if(t_100us_10ms_cnt >= 100) //10ms { t_100us_10ms_cnt = 0; run_10ms_flag = 1; t_10ms_cnt++; } led_cnt++; if(led_cnt > 10) { led_cnt = 0; Led_Scan(); } } if(RAIF) RAIF = 0; //清中断标志 if(RBIF) RBIF = 0; //清中断标志 }
06-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值