LPC1700系列编程基础
1. 开发环境搭建
在开始LPC1700系列的编程之前,首先需要搭建一个合适的开发环境。LPC1700系列基于ARM Cortex-M3内核,常见的开发环境包括Keil uVision和LPCXpresso。本节将详细介绍如何搭建这些开发环境。
1.1 Keil uVision开发环境搭建
Keil uVision是一款广泛使用的集成开发环境(IDE),支持多种ARM内核的单片机开发。以下是搭建Keil uVision开发环境的步骤:
-
下载并安装Keil uVision:
- 访问Keil官网(https://www2.keil.com/)下载最新版本的Keil uVision。
- 按照安装向导的提示完成安装。
-
安装LPC1700系列支持包:
- 打开Keil uVision。
- 选择
Project
->New uVision Project
。 - 在弹出的对话框中选择LPC1700系列的芯片型号,例如LPC1768。
- 点击
Next
,选择ARM
->Cortex-M3
->LPC17xx
,然后点击Next
。 - 选择
Use default settings for Target
,点击Finish
。
-
配置硬件调试工具:
- 选择
Project
->Options for Target
。 - 在
Target
选项卡中选择合适的调试工具,例如LPC-Link2。 - 在
Debug
选项卡中选择Use
->CMSIS-DAP Debugger
。
- 选择
-
创建项目文件:
- 在项目目录中创建一个新的文件夹,例如
LPC1700_Project
。 - 将必要的源文件和库文件添加到项目中。
- 创建主程序文件
main.c
。
- 在项目目录中创建一个新的文件夹,例如
1.2 LPCXpresso开发环境搭建
LPCXpresso是NXP官方提供的集成开发环境,专门为LPC系列单片机设计。以下是搭建LPCXpresso开发环境的步骤:
-
下载并安装LPCXpresso:
- 访问NXP官网(https://www.nxp.com/)下载LPCXpresso IDE。
- 按照安装向导的提示完成安装。
-
安装LPC1700系列支持包:
- 打开LPCXpresso。
- 选择
File
->New
->LPCXpresso Project
。 - 在弹出的对话框中选择
LPC1768
芯片型号,点击Next
。 - 选择
Use default settings for Target
,点击Finish
。
-
配置硬件调试工具:
- 选择
Project
->Properties
。 - 在
C/C++ Build
选项卡中配置编译器设置。 - 在
Debug
选项卡中选择合适的调试工具,例如LPC-Link2。
- 选择
-
创建项目文件:
- 在项目目录中创建一个新的文件夹,例如
LPC1700_Project
。 - 将必要的源文件和库文件添加到项目中。
- 创建主程序文件
main.c
。
- 在项目目录中创建一个新的文件夹,例如
2. 基本硬件初始化
在开始编写应用程序之前,需要对LPC1700系列的硬件进行初始化。这包括时钟配置、GPIO初始化、中断配置等。本节将详细介绍这些初始化步骤。
2.1 时钟配置
LPC1700系列的时钟源可以是内部振荡器或外部晶振。以下是一个时钟配置的例子:
#include "LPC17xx.h" // 导入LPC1700系列的头文件
void SystemInit(void) {
// 使能外部晶振
LPC_SC->CCLKSEL = 0x00; // 选择外部晶振作为主时钟源
LPC_SC->CCLKCFG = 0x07; // 设置主时钟分频因子
LPC_SC->PLL0CON = 0x01; // 使能PLL0
LPC_SC->PLL0CFG = 0x24; // 设置PLL0配置
LPC_SC->PLL0CON = 0x03; // 连接PLL0
LPC_SC->CCLKSEL = 0x01; // 选择PLL0输出作为系统时钟源
LPC_SC->PLL0STAT = 0x03; // 确认PLL0状态
LPC_SC->SYSOSCCTRL = 0x02; // 使能外部晶振
LPC_SC->PDRUNCFG &= ~(1 << 5); // 使能外部晶振
LPC_SC->CCLKCFG = 0x07; // 设置系统时钟分频因子
}
int main(void) {
SystemInit(); // 初始化系统时钟
// 其他初始化代码
while (1) {
// 主程序
}
}
2.2 GPIO初始化
LPC1700系列的GPIO(通用输入输出)接口可以用于控制外部设备。以下是一个GPIO初始化的例子:
#include "LPC17xx.h"
void GPIO_Init(void) {
// 设置P0.0为输出模式
LPC_PINCON->PINSEL0 &= ~(3 << 0); // 清除P0.0的位选择
LPC_PINCON->PINSEL0 |= (0 << 0); // 设置P0.0为GPIO
LPC_GPIO0->FIODIR |= (1 << 0); // 设置P0.0为输出
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
while (1) {
LPC_GPIO0->FIOSET = (1 << 0); // 设置P0.0为高电平
LPC_SC->PCON |= (1 << 0); // 使能电源管理
LPC_SC->PCON &= ~(1 << 0); // 清除电源管理
LPC_GPIO0->FIOCLR = (1 << 0); // 设置P0.0为低电平
}
}
2.3 中断配置
LPC1700系列支持多种中断源,中断配置是实现复杂功能的重要步骤。以下是一个中断配置的例子:
#include "LPC17xx.h"
#include "NXP_LPC1700.h" // 导入LPC1700系列的库文件
void EINT3_IRQHandler(void) __attribute__((interrupt("IRQ"))); // 中断处理函数声明
void EINT3_IRQHandler(void) {
// 中断处理代码
LPC_SC->EXTINT = (1 << 3); // 清除外部中断3的状态
}
void NVIC_Init(void) {
// 使能外部中断3
LPC_SC->EXTMODE |= (1 << 3); // 设置外部中断3为边沿触发
LPC_SC->EXTPOLAR &= ~(1 << 3); // 设置外部中断3为下降沿触发
NVIC_EnableIRQ(EINT3_IRQn); // 使能外部中断3的中断
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
// 设置P0.3为输入模式
LPC_PINCON->PINSEL6 &= ~(0x03 << 0); // 清除P0.3的位选择
LPC_PINCON->PINSEL6 |= (0x01 << 0); // 设置P0.3为GPIO
LPC_GPIO0->FIODIR &= ~(1 << 3); // 设置P0.3为输入
while (1) {
// 主程序
}
}
3. 基本外设使用
LPC1700系列包含多种外设,如UART、I2C、SPI等。本节将详细介绍如何使用这些外设。
3.1 UART通信
UART(通用异步收发传输器)是常用的串行通信接口。以下是一个UART通信的例子:
#include "LPC17xx.h"
void UART_Init(void) {
// 使能UART0的时钟
LPC_SC->PCONP |= (1 << 3); // 使能UART0的时钟
// 设置UART0的波特率
LPC_UART0->LCR = 0x83; // 使能DLAB,设置8位数据,无校验,1位停止位
LPC_UART0->DLL = 0x61; // 设置波特率分频低8位
LPC_UART0->DLM = 0x00; // 设置波特率分频高8位
LPC_UART0->LCR = 0x03; // 清除DLAB
// 设置UART0的FIFO
LPC_UART0->FCR = 0x07; // 使能FIFO,设置触发点为1个字节
// 使能UART0的发送和接收
LPC_UART0->IER = 0x03; // 使能发送和接收中断
}
void UART_SendChar(char ch) {
while (!(LPC_UART0->LSR & 0x20)); // 等待发送缓冲区为空
LPC_UART0->THR = ch; // 发送字符
}
void UART_SendString(char *str) {
while (*str) {
UART_SendChar(*str++);
}
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
UART_Init(); // 初始化UART
while (1) {
UART_SendString("Hello, LPC1700!\r\n"); // 发送字符串
LPC_SC->PCON |= (1 << 0); // 使能电源管理
LPC_SC->PCON &= ~(1 << 0); // 清除电源管理
}
}
3.2 I2C通信
I2C(内部集成电路总线)是一种用于短距离通信的串行总线。以下是一个I2C通信的例子:
#include "LPC17xx.h"
void I2C_Init(void) {
// 使能I2C0的时钟
LPC_SC->PCONP |= (1 << 24); // 使能I2C0的时钟
// 设置I2C0的引脚
LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & (~0x000000F0)) | 0x000000A0; // 设置P0.10和P0.11为I2C
LPC_PINCON->PINMODE3 = (LPC_PINCON->PINMODE3 & (~0x000000F0)) | 0x000000A0; // 设置引脚模式为标准模式
// 配置I2C0
LPC_I2C0->CON = 0x00; // 设置为标准模式
LPC_I2C0->SA = 0x5A; // 设置I2C地址
LPC_I2C0->ADR = 0x00; // 清除从机地址
LPC_I2C0->SCLH = 0x0F; // 设置SCL高周期
LPC_I2C0->SCLL = 0x0F; // 设置SCL低周期
LPC_I2C0->CON |= 0x40; // 使能I2C
}
void I2C_Write(uint8_t address, uint8_t reg, uint8_t data) {
LPC_I2C0->CONCLR = 0x03; // 清除起始和停止条件
LPC_I2C0->CONSET = 0x01; // 使能I2C起始条件
// 等待I2C空闲
while (LPC_I2C0->STAT != 0x08);
// 发送从机地址(写模式)
LPC_I2C0->DAT = (address << 1) | 0x00;
while (LPC_I2C0->STAT != 0x18);
// 发送寄存器地址
LPC_I2C0->DAT = reg;
while (LPC_I2C0->STAT != 0x28);
// 发送数据
LPC_I2C0->DAT = data;
while (LPC_I2C0->STAT != 0x28);
// 生成停止条件
LPC_I2C0->CONCLR = 0x02; // 清除停止条件
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
I2C_Init(); // 初始化I2C
while (1) {
I2C_Write(0x50, 0x01, 0x55); // 写入数据到从机地址0x50的寄存器0x01
LPC_SC->PCON |= (1 << 0); // 使能电源管理
LPC_SC->PCON &= ~(1 << 0); // 清除电源管理
}
}
3.3 SPI通信
SPI(串行外设接口)是一种全双工同步串行通信接口。以下是一个SPI通信的例子:
#include "LPC17xx.h"
void SPI_Init(void) {
// 使能SPI0的时钟
LPC_SC->PCONP |= (1 << 11); // 使能SPI0的时钟
// 设置SPI0的引脚
LPC_PINCON->PINSEL0 = (LPC_PINCON->PINSEL0 & (~0x0000000F)) | 0x0000000A; // 设置P0.0为MISO,P0.1为MOSI
LPC_PINCON->PINSEL1 = (LPC_PINCON->PINSEL1 & (~0x0000000F)) | 0x00000002; // 设置P0.4为SCLK
LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & (~0x0000000F)) | 0x00000000; // 设置P0.16为NSS
// 配置SPI0
LPC_SPI0->SPCR = 0x00; // 清除SPI控制寄存器
LPC_SPI0->SPCR = 0x30; // 使能SPI主模式,设置数据长度为8位
LPC_SPI0->SPCCR = 0x01; // 设置波特率分频因子
}
void SPI_Write(uint8_t data) {
// 等待SPI空闲
while (!(LPC_SPI0->SPSR & 0x20));
// 发送数据
LPC_SPI0->SPDR = data;
// 等待数据传输完成
while (!(LPC_SPI0->SPSR & 0x10));
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
SPI_Init(); // 初始化SPI
while (1) {
SPI_Write(0x55); // 发送数据0x55
LPC_SC->PCON |= (1 << 0); // 使能电源管理
LPC_SC->PCON &= ~(1 << 0); // 清除电源管理
}
}
4. 中断处理
中断处理是嵌入式系统中重要的功能,可以实现对外部事件的快速响应。以下是一个中断处理的例子:
#include "LPC17xx.h"
#include "NXP_LPC1700.h"
void EINT3_IRQHandler(void) __attribute__((interrupt("IRQ"))); // 中断处理函数声明
void EINT3_IRQHandler(void) {
// 中断处理代码
LPC_SC->EXTINT = (1 << 3); // 清除外部中断3的状态
LPC_GPIO0->FIOCLR = (1 << 0); // 设置P0.0为低电平
}
void NVIC_Init(void) {
// 使能外部中断3
LPC_SC->EXTMODE |= (1 << 3); // 设置外部中断3为边沿触发
LPC_SC->EXTPOLAR &= ~(1 << 3); // 设置外部中断3为下降沿触发
NVIC_EnableIRQ(EINT3_IRQn); // 使能外部中断3的中断
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
// 设置P0.3为输入模式
LPC_PINCON->PINSEL6 &= ~(0x03 << 0); // 清除P0.3的位选择
LPC_PINCON->PINSEL6 |= (0x01 << 0); // 设置P0.3为GPIO
LPC_GPIO0->FIODIR &= ~(1 << 3); // 设置P0.3为输入
while (1) {
// 主程序
}
}
5. 定时器使用
LPC1700系列包含多个定时器,可以用于产生定时中断或控制外部设备。以下是一个定时器的例子:
5.1 定时器初始化
在使用定时器之前,需要对其进行初始化。这包括使能定时器的时钟、配置定时器的预分频器和匹配寄存器等。以下是一个定时器0的初始化示例:
#include "LPC17xx.h"
void Timer_Init(void) {
// 使能定时器0的时钟
LPC_SC->PCONP |= (1 << 22); // 使能定时器0的时钟
// 配置定时器0
LPC_TIM0->TCR = 0x02; // 使能定时器复位
LPC_TIM0->PR = 0x00; // 设置预分频器为0
LPC_TIM0->MR0 = 100000; // 设置匹配寄存器0为100000个时钟周期
LPC_TIM0->MCR = 0x04; // 设置中断模式为定时器匹配
LPC_TIM0->TCR = 0x01; // 启动定时器
}
void Timer0_IRQHandler(void) {
// 定时器0中断处理代码
LPC_TIM0->IR = 0x01; // 清除定时器0中断标志
LPC_GPIO0->FIOCLR = (1 << 0); // 设置P0.0为低电平
LPC_GPIO0->FIOSET = (1 << 0); // 设置P0.0为高电平
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
Timer_Init(); // 初始化定时器0
// 使能定时器0中断
NVIC_EnableIRQ(TIMER0_IRQn);
while (1) {
// 主程序
}
}
5.2 定时器中断配置
定时器中断配置是实现定时功能的关键步骤。以下是一个定时器0中断配置的示例:
#include "LPC17xx.h"
void Timer_Init(void) {
// 使能定时器0的时钟
LPC_SC->PCONP |= (1 << 22); // 使能定时器0的时钟
// 配置定时器0
LPC_TIM0->TCR = 0x02; // 使能定时器复位
LPC_TIM0->PR = 0x00; // 设置预分频器为0
LPC_TIM0->MR0 = 100000; // 设置匹配寄存器0为100000个时钟周期
LPC_TIM0->MCR = 0x04; // 设置中断模式为定时器匹配
LPC_TIM0->TCR = 0x01; // 启动定时器
}
void Timer0_IRQHandler(void) {
// 定时器0中断处理代码
LPC_TIM0->IR = 0x01; // 清除定时器0中断标志
LPC_GPIO0->FIOCLR = (1 << 0); // 设置P0.0为低电平
LPC_GPIO0->FIOSET = (1 << 0); // 设置P0.0为高电平
}
void NVIC_Init(void) {
// 使能定时器0中断
NVIC_EnableIRQ(TIMER0_IRQn);
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
Timer_Init(); // 初始化定时器0
while (1) {
// 主程序
}
}
5.3 定时器应用示例
定时器可以用于多种应用,例如周期性地执行某个任务或控制外部设备。以下是一个使用定时器0控制LED闪烁的示例:
#include "LPC17xx.h"
void Timer_Init(void) {
// 使能定时器0的时钟
LPC_SC->PCONP |= (1 << 22); // 使能定时器0的时钟
// 配置定时器0
LPC_TIM0->TCR = 0x02; // 使能定时器复位
LPC_TIM0->PR = 0x00; // 设置预分频器为0
LPC_TIM0->MR0 = 100000; // 设置匹配寄存器0为100000个时钟周期
LPC_TIM0->MCR = 0x04; // 设置中断模式为定时器匹配
LPC_TIM0->TCR = 0x01; // 启动定时器
}
void Timer0_IRQHandler(void) {
// 定时器0中断处理代码
LPC_TIM0->IR = 0x01; // 清除定时器0中断标志
static uint8_t led_state = 0;
if (led_state) {
LPC_GPIO0->FIOCLR = (1 << 0); // 设置P0.0为低电平
} else {
LPC_GPIO0->FIOSET = (1 << 0); // 设置P0.0为高电平
}
led_state = !led_state; // 切换LED状态
}
void GPIO_Init(void) {
// 设置P0.0为输出模式
LPC_PINCON->PINSEL0 &= ~(3 << 0); // 清除P0.0的位选择
LPC_PINCON->PINSEL0 |= (0 << 0); // 设置P0.0为GPIO
LPC_GPIO0->FIODIR |= (1 << 0); // 设置P0.0为输出
}
void NVIC_Init(void) {
// 使能定时器0中断
NVIC_EnableIRQ(TIMER0_IRQn);
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
Timer_Init(); // 初始化定时器0
while (1) {
// 主程序
}
}
6. PWM(脉冲宽度调制)使用
LPC1700系列支持PWM(脉冲宽度调制)功能,可以用于控制电机、LED亮度等。以下是一个PWM使用的例子:
6.1 PWM初始化
在使用PWM之前,需要对其进行初始化。这包括使能PWM的时钟、配置PWM的寄存器等。以下是一个PWM初始化的示例:
#include "LPC17xx.h"
void PWM_Init(void) {
// 使能PWM的时钟
LPC_SC->PCONP |= (1 << 15); // 使能PWM的时钟
// 设置PWM的引脚
LPC_PINCON->PINSEL4 = (LPC_PINCON->PINSEL4 & (~0x0000000F)) | 0x0000000A; // 设置P0.18和P0.19为PWM
// 配置PWM
LPC_PWM1->PCR = 0x00; // 清除PWM控制寄存器
LPC_PWM1->PCR = 0x03; // 使能PWM0和PWM1
LPC_PWM1->LER = 0x00; // 清除匹配加载寄存器
LPC_PWM1->LER = 0x03; // 使能匹配0和匹配1
LPC_PWM1->MR0 = 100000; // 设置匹配寄存器0为100000个时钟周期
LPC_PWM1->MR1 = 50000; // 设置匹配寄存器1为50000个时钟周期
LPC_PWM1->TCR = 0x02; // 使能定时器复位
LPC_PWM1->TCR = 0x01; // 启动PWM
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
PWM_Init(); // 初始化PWM
while (1) {
// 主程序
}
}
6.2 PWM应用示例
PWM可以用于控制电机的速度或LED的亮度。以下是一个使用PWM控制LED亮度的示例:
#include "LPC17xx.h"
void PWM_Init(void) {
// 使能PWM的时钟
LPC_SC->PCONP |= (1 << 15); // 使能PWM的时钟
// 设置PWM的引脚
LPC_PINCON->PINSEL4 = (LPC_PINCON->PINSEL4 & (~0x0000000F)) | 0x0000000A; // 设置P0.18和P0.19为PWM
// 配置PWM
LPC_PWM1->PCR = 0x00; // 清除PWM控制寄存器
LPC_PWM1->PCR = 0x03; // 使能PWM0和PWM1
LPC_PWM1->LER = 0x00; // 清除匹配加载寄存器
LPC_PWM1->LER = 0x03; // 使能匹配0和匹配1
LPC_PWM1->MR0 = 100000; // 设置匹配寄存器0为100000个时钟周期
LPC_PWM1->MR1 = 50000; // 设置匹配寄存器1为50000个时钟周期
LPC_PWM1->TCR = 0x02; // 使能定时器复位
LPC_PWM1->TCR = 0x01; // 启动PWM
}
void PWM_SetDutyCycle(uint32_t channel, uint32_t duty_cycle) {
// 设置PWM通道的占空比
switch (channel) {
case 0:
LPC_PWM1->MR1 = (LPC_PWM1->MR0 * duty_cycle) / 100;
break;
case 1:
LPC_PWM1->MR2 = (LPC_PWM1->MR0 * duty_cycle) / 100;
break;
// 可以添加更多通道
}
}
int main(void) {
SystemInit(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO
NVIC_Init(); // 初始化NVIC
PWM_Init(); // 初始化PWM
while (1) {
PWM_SetDutyCycle(0, 25); // 设置PWM0的占空比为25%
for (volatile uint32_t i = 0; i < 500000; i++); // 延时
PWM_SetDutyCycle(0, 50); // 设置PWM0的占空比为50%
for (volatile uint32_t i = 0; i < 500000; i++); // 延时
PWM_SetDutyCycle(0, 75); // 设置PWM0的占空比为75%
for (volatile uint32_t i = 0; i < 500000; i++); // 延时
PWM_SetDutyCycle(0, 100); // 设置PWM0的占空比为100%
for (volatile uint32_t i = 0; i < 500000; i++); // 延时
}
}
7. 总结
通过以上内容,我们详细介绍了如何搭建LPC1700系列的开发环境,包括Keil uVision和LPCXpresso。此外,我们还介绍了基本的硬件初始化步骤,如时钟配置、GPIO初始化和中断配置。最后,我们展示了如何使用LPC1700系列的常见外设,如UART、I2C、SPI和PWM。
希望这些内容能够帮助你更好地理解和使用LPC1700系列单片机。如果你有任何问题或需要进一步的帮助,请随时查阅官方文档或在线资源。