学习LPC17xx – ADC
LPC17xx的ADC可以工作于两种模式:软件突发模式和自动模式。软件突发模式下,每一次转换都需要软件去触发。自动模式下,ADC会自动去转换选定的通道,并可选的触发中断。以下代码分别为软件突发和自动转换。
- Burst模式指的是由硬件自动控制,非Burst每次必须手动Start。
- 时钟频率不能超过200,000 Hz
#include <lpc17xx.h> #include "lpc17xx_libcfg.h" #include <debug_frmwrk.h> #include <lpc17xx_nvic.h> #include <lpc17xx_pinsel.h> #include <lpc17xx_adc.h> volatile int SysTickCnt; void SysTick_Handler(void) { SysTickCnt++; } int main(void) { int prv; PINSEL_CFG_Type pincfg; SYSTICK_InternalInit(10); //the maximum value should not exceed the 24 bit systick counter SYSTICK_Cmd(ENABLE); SYSTICK_IntCmd(ENABLE); debug_frmwrk_init(); _DBG_("ADC Test"); pincfg.Portnum = PINSEL_PORT_1; pincfg.Pinnum = PINSEL_PIN_31; pincfg.Funcnum = PINSEL_FUNC_3; pincfg.Pinmode = PINSEL_PINMODE_TRISTATE; pincfg.OpenDrain = PINSEL_PINMODE_NORMAL; PINSEL_ConfigPin(&pincfg); ADC_Init(LPC_ADC, 200000); ADC_ChannelCmd(LPC_ADC, 5, ENABLE); ADC_BurstCmd(LPC_ADC, DISABLE); while(1) { ADC_StartCmd(LPC_ADC, ADC_START_NOW); while(!ADC_ChannelGetStatus(LPC_ADC, 5, 1)); _DBD16(ADC_ChannelGetData(LPC_ADC, 5)); _DBG_(""); prv = SysTickCnt; while(SysTickCnt < prv + 10); } } |
#include <lpc17xx.h> #include "lpc17xx_libcfg.h" #include <debug_frmwrk.h> #include <lpc17xx_nvic.h> #include <lpc17xx_pinsel.h> #include <lpc17xx_adc.h> volatile int SysTickCnt; void SysTick_Handler(void) { SysTickCnt++; } int main(void) { int prv; PINSEL_CFG_Type pincfg; SYSTICK_InternalInit(10); //the maximum value should not exceed the 24 bit systick counter SYSTICK_Cmd(ENABLE); SYSTICK_IntCmd(ENABLE); debug_frmwrk_init(); _DBG_("ADC Test"); pincfg.Portnum = PINSEL_PORT_1; pincfg.Pinnum = PINSEL_PIN_31; pincfg.Funcnum = PINSEL_FUNC_3; pincfg.Pinmode = PINSEL_PINMODE_TRISTATE; pincfg.OpenDrain = PINSEL_PINMODE_NORMAL; PINSEL_ConfigPin(&pincfg); pincfg.Portnum = PINSEL_PORT_0; pincfg.Pinnum = PINSEL_PIN_26; pincfg.Funcnum = PINSEL_FUNC_1; pincfg.Pinmode = PINSEL_PINMODE_TRISTATE; pincfg.OpenDrain = PINSEL_PINMODE_NORMAL; PINSEL_ConfigPin(&pincfg); ADC_Init(LPC_ADC, 200000); ADC_ChannelCmd(LPC_ADC, 3, ENABLE); ADC_ChannelCmd(LPC_ADC, 5, ENABLE); ADC_BurstCmd(LPC_ADC, ENABLE); ADC_StartCmd(LPC_ADC, ADC_START_CONTINUOUS); while(1) { while(!ADC_ChannelGetStatus(LPC_ADC, 5, 1)); _DBD16(ADC_ChannelGetData(LPC_ADC, 5)); _DBG_(" : Channel 5"); while(!ADC_ChannelGetStatus(LPC_ADC, 3, 1)); _DBD16(ADC_ChannelGetData(LPC_ADC, 3)); _DBG_(" : Channel 3"); prv = SysTickCnt; while(SysTickCnt < prv + 10); } } |
学习LPC17xx – PWM
PWM和Timer类似,唯一不同的是它有6个输出匹配通道,而且可以配置为双边沿模式,即每路的PWM可以不是共边沿的。笔记、代码和输出效果如下:
- PWM_ChannelConfig不能用在通道1上,因为通道1不可能作为双边沿输出。
- PWM_Cmd仅使能PWM输出,PWM_CounterCmd才会启动定时器,才真正开始。
学习LPC17xx – SysTick和RIT
SysTick是Cortex M3内置的定时器(而不是LPC1700系列特有的),通常用来做操作系统的时钟节拍。RIT是重复中断定时器,与SysTick类似,只是这是LPC1700特有的。下面是调试笔记和示例代码。
- 进入中断后一定要取消标志位。RIT_GetIntStatus(LPC_RIT)就是干这事的。
- 固件库中用到的RITx全部是LPC_RIT
- RITENBR寄存器(调试的时候让定时器停下来)是指调试时按Stop。
- 在Watch窗口里面看寄存器要加”`”,就像”`RICOUNTER”。
- 所有寄存器都在Symbols窗口里面有。
- 功率控制默认是关闭的。
- 时钟可以PCLKSEL#寄存器中设置。
#include <lpc17xx.h> #include "lpc17xx_libcfg.h" #include <debug_frmwrk.h> #include <lpc17xx_nvic.h> #include <lpc17xx_systick.h> #include <lpc17xx_rit.h> void SysTick_Handler(void) { static uint32_t t; ++ t; if (!(t % 10)) _DBG_("SysTick IRQ"); } void RIT_IRQHandler(void) { RIT_GetIntStatus(LPC_RIT); _DBG_("RIT IRQ"); } int main(void) { debug_frmwrk_init(); SYSTICK_InternalInit(100); //the maximum value should not exceed the 24 bit systick counter SYSTICK_Cmd(ENABLE); SYSTICK_IntCmd(ENABLE); RIT_Init(LPC_RIT); RIT_TimerConfig(LPC_RIT, 500); //100ms RIT_TimerDebugCmd(LPC_RIT, DISABLE); NVIC_EnableIRQ(RIT_IRQn); while(1); } |
学习LPC17xx – 定时器
定时器部分的固件库有Bug,具体为作为计数器模式的时候固件库工作不正常,检查代码后发现有几处错误,此问题已反馈给NXP。
- PCLK默认是CCLK四分频,固件库初始化时会修改为四分频,所以需要改变PCLK的分频应当在用固件库初始化之后。
- 这里的GetIntStatus是不会清空挂起位的。这与RIT不同。
- 固件库对Counter模式有很多错误,固件库手册描述不清等。
- 固件库中[320行附近]:CCR和CTCR混淆,TIM_TIMER_MODE应为TimerCounterMode。
- TIM_COUNTERCFG_Type的说明在另外一处,Init函数接受的第三个参数为void*,具体类型通过第二个参数选择。TIM_COUNTERCFG_Type说明处有错误。事实上第一个元素没用到,第二个参数的描述应为第一个参数。
- 固件库中[344行附近]:CCR和CTCR混淆。
- 头文件[142行附近]还有对参数检查的错误,把计数器模式的下降沿和任意边沿都写成了上升沿。
- 固件库中应该还有错误,比如GetIntStatus和GetIntCaptureStatus函数。
- 要记得引脚选择。
- 有空要调试好固件库。
以下代码分别为使用定时器0和2、捕获输入、计数器模式(需要修改固件库)。
阅读更多
学习LPC17xx – GPIO和EXTI
以下是GPIO和EXTI的调试笔记:
- 所有引脚使用前必须初始化(一般来说GPIO除外)。包括EXTI。
- GPIO需要设置方向、输出等。通过SetValue和ClearValue就可以了。FIO打头的函数貌似是为了兼容以前的。
- EINT0是通过PINSEL使能的,PCONP中没有对应位。
- NVIC的控制是在core_cm3.h中定义的。SysTick既有LPC17xx的驱动库,也在CMSIS中就有定义。
- 中断使用前要通过NVIC使能中断。
- 进入中断后要清除中断标志位。
- 中断后Pending位自动清零(当中断变为Active后),但标志位不会。
- SysTick的溢出时间不能超过24位寄存器。
- 即使没有使能NVIC中对应的中断,当其触发时,仍然会变成Pending。
- SysTick不能用NVIC控制。
- 注意看手册,GPIO中断一次是设置一批的。
- 消抖:群里有人说不要用外部中断。进入中断后判断端口的电平。计数,到一定阈值以上才算真正触发。(但是这种办法在外部中断(EINT/EXTI)中可能无法实现)
- SysTick的时钟固定为CCLK。


