5. 外设接口详解
5.1 GPIO(通用输入输出端口)
5.1.1 GPIO 基本原理
通用输入输出端口(GPIO)是单片机中最基本的外设接口之一,用于控制外部设备的输入和输出。GPIO 可以配置为输入或输出模式,具有多种功能,如中断检测、上拉/下拉电阻配置等。LPC1100 系列单片机的 GPIO 端口通常由多个寄存器控制,包括数据寄存器、方向寄存器、中断寄存器等。
5.1.2 GPIO 寄存器
LPC1100 系列单片机的 GPIO 寄存器主要包括以下几类:
- 数据寄存器(FIOxSET 和 FIOxCLR):用于设置或清除端口的输出值。
- 方向寄存器(FIODIR):用于配置端口的方向,即输入或输出。
- 中断寄存器(FIOINTENSET/FIOINTENCLR、FIOINTSTATR/FIOINTSTATF、FIOINTSTATR):用于配置和检测 GPIO 中断。
- 状态寄存器(FIOPIN):用于读取端口的输入值。
5.1.3 GPIO 配置
GPIO 的配置通常包括以下几个步骤:
- 配置端口方向:使用
FIODIR
寄存器设置端口为输入或输出。 - 设置初始输出值:使用
FIOxSET
和FIOxCLR
寄存器设置端口的初始输出值。 - 配置中断:使用
FIOINTENSET
和FIOINTENCLR
寄存器启用或禁用中断,使用FIOINTSTATR
和FIOINTSTATF
寄存器检测中断状态。
5.1.4 GPIO 示例
5.1.4.1 配置 GPIO 为输出
以下示例代码展示了如何配置 GPIO 为输出并控制 LED 的亮灭:
#include "LPC11xx.h"
#define LED_PORT (1) // LED 连接在 PORT1
#define LED_PIN (21) // LED 连接在 PIN21
void GPIO_Init(void) {
// 配置 GPIO 方向
LPC_GPIO1->DIR |= (1 << LED_PIN); // 设置 GPIO1 的 PIN21 为输出
}
void LED_Toggle(void) {
// 切换 LED 状态
LPC_GPIO1->DATA ^= (1 << LED_PIN); // 切换 GPIO1 的 PIN21 输出值
}
int main(void) {
// 初始化 GPIO
GPIO_Init();
while (1) {
LED_Toggle(); // 切换 LED 状态
for (int i = 0; i < 1000000; i++) { // 延时
__NOP();
}
}
}
5.1.4.2 配置 GPIO 为输入并检测按键
以下示例代码展示了如何配置 GPIO 为输入并检测按键的状态:
#include "LPC11xx.h"
#define BUTTON_PORT (0) // 按键连接在 PORT0
#define BUTTON_PIN (7) // 按键连接在 PIN7
void GPIO_Init(void) {
// 配置 GPIO 方向
LPC_GPIO0->DIR &= ~(1 << BUTTON_PIN); // 设置 GPIO0 的 PIN7 为输入
LPC_GPIO0->DIR |= (1 << LED_PIN); // 设置 GPIO1 的 PIN21 为输出
}
void GPIO_ISR(void) __attribute__((naked));
void GPIO_ISR(void) {
// 中断处理函数
if (LPC_GPIO0->INTSTATR & (1 << BUTTON_PIN)) {
// 按键被按下
LPC_GPIO1->DATA ^= (1 << LED_PIN); // 切换 LED 状态
LPC_GPIO0->INTCLR = (1 << BUTTON_PIN); // 清除中断标志
}
}
int main(void) {
// 初始化 GPIO
GPIO_Init();
// 启用按键中断
LPC_GPIO0->INTENSET = (1 << BUTTON_PIN); // 启用 GPIO0 的 PIN7 中断
NVIC_EnableIRQ(GPIO0_IRQn); // 启用 GPIO0 中断
while (1) {
// 主循环
}
}
5.1.5 GPIO 中断配置
GPIO 中断配置包括以下几个步骤:
- 配置中断源:使用
FIOINTENSET
寄存器启用特定的中断源。 - 配置中断触发条件:使用
FIOINTMODE
寄存器设置中断触发条件,如上升沿、下降沿或电平触发。 - 配置中断优先级:使用 NVIC(嵌套向量中断控制器)配置中断优先级。
- 编写中断处理函数:编写中断处理函数,处理中断事件。
5.1.6 GPIO 性能优化
- 时序优化:合理设置延时,确保 GPIO 的切换频率符合系统要求。
- 功耗优化:在不需要使用 GPIO 时,将其配置为高阻态以降低功耗。
- 中断处理优化:减少中断处理函数的执行时间,提高系统的响应速度。
5.2 UART(通用异步收发传输器)
5.2.1 UART 基本原理
通用异步收发传输器(UART)用于实现串行通信,可以发送和接收数据。LPC1100 系列单片机的 UART 模块通常包括发送器、接收器和波特率生成器等组件。
5.2.2 UART 寄存器
LPC1100 系列单片机的 UART 寄存器主要包括以下几类:
- 数据寄存器(USARTx_THR/USARTx_RBR):用于发送和接收数据。
- 状态寄存器(USARTx_IIR/USARTx_ISR、USARTx_LSR):用于检测 UART 的状态,如接收缓冲区是否为空、发送缓冲区是否满等。
- 控制寄存器(USARTx_LCR、USARTx_FCR、USARTx_MCR):用于配置 UART 的工作模式,如波特率、数据位、停止位等。
- 波特率寄存器(USARTx_DLL/USARTx_DLM):用于设置 UART 的波特率。
5.2.3 UART 配置
UART 的配置通常包括以下几个步骤:
- 配置波特率:根据通信需求设置波特率。
- 配置数据格式:设置数据位、停止位和校验位。
- 使能 UART 模块:使能 UART 模块并配置中断。
- 初始化 UART:初始化 UART 的寄存器。
5.2.4 UART 示例
5.2.4.1 初始化 UART
以下示例代码展示了如何初始化 UART0,配置其波特率为 9600,并发送字符串 “Hello, World!”:
#include "LPC11xx.h"
void UART_Init(void) {
// 使能 UART0 时钟
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 12); // 使能 UART0 时钟
// 配置波特率
LPC_USART0->LCR = 0x83; // 8 位数据,无校验,1 位停止位,使能除法器
LPC_USART0->DLL = 12; // 设置 DLL 寄存器
LPC_USART0->DLM = 0; // 设置 DLM 寄存器
LPC_USART0->LCR = 0x03; // 8 位数据,无校验,1 位停止位
// 使能 FIFO
LPC_USART0->FCR = 0x07; // 使能 FIFO,并清空接收和发送 FIFO
// 配置中断
LPC_USART0->IER = 0x01; // 使能接收中断
NVIC_EnableIRQ(USART0_IRQn); // 使能 USART0 中断
}
void UART_SendChar(char ch) {
while (!(LPC_USART0->LSR & 0x20)); // 等待发送缓冲区为空
LPC_USART0->THR = ch; // 发送字符
}
void UART_SendString(char *str) {
while (*str) {
UART_SendChar(*str++); // 发送字符串中的每个字符
}
}
void USART0_IRQHandler(void) {
// UART0 中断处理函数
if (LPC_USART0->IIR & 0x01) {
char ch = LPC_USART0->RBR; // 读取接收缓冲区中的字符
UART_SendChar(ch); // 发送接收到的字符
}
}
int main(void) {
// 初始化 UART
UART_Init();
// 发送字符串
UART_SendString("Hello, World!");
while (1) {
// 主循环
}
}
5.2.5 UART 通信协议
UART 通信协议包括以下几个要素:
- 波特率:通信速率,通常以 bps(位每秒)为单位。
- 数据位:数据帧中的数据位数,通常为 5 到 8 位。
- 停止位:数据帧结束时的位数,通常为 1 或 2 位。
- 校验位:用于数据校验,可以是奇校验、偶校验或无校验。
5.2.6 UART 性能优化
- 波特率优化:根据通信需求选择合适的波特率,提高通信效率。
- 中断处理优化:减少中断处理函数的执行时间,提高系统的响应速度。
- 数据缓冲优化:使用缓冲区管理数据流,减少数据溢出的风险。
5.3 SPI(串行外设接口)
5.3.1 SPI 基本原理
串行外设接口(SPI)是一种同步串行通信接口,用于主设备和从设备之间的高速通信。SPI 通常包括四条信号线:MOSI(主设备输出,从设备输入)、MISO(主设备输入,从设备输出)、SCLK(时钟信号)和 SS(从设备选择信号)。
5.3.2 SPI 寄存器
LPC1100 系列单片机的 SPI 寄存器主要包括以下几类:
- 控制寄存器(SPIxCR、SPIxCFG):用于配置 SPI 的工作模式,如主模式或从模式、数据长度等。
- 状态寄存器(SPIxSTAT):用于检测 SPI 的状态,如数据是否准备好、错误状态等。
- 数据寄存器(SPIxTXDAT、SPIxRXDAT):用于发送和接收数据。
- 中断寄存器(SPIxINTEN、SPIxINTSTAT):用于配置和检测 SPI 中断。
5.3.3 SPI 配置
SPI 的配置通常包括以下几个步骤:
- 配置 SPI 模式:选择主模式或从模式。
- 配置数据长度:设置数据帧的长度。
- 配置时钟极性和相位:设置 SCLK 的极性和相位。
- 使能 SPI 模块:使能 SPI 模块并配置中断。
5.3.4 SPI 示例
5.3.4.1 初始化 SPI
以下示例代码展示了如何初始化 SPI0,配置其为主模式,并发送和接收数据:
#include "LPC11xx.h"
#define SPI0_PORT (0)
#define SPI0_MOSI_PIN (25)
#define SPI0_MISO_PIN (26)
#define SPI0_SCLK_PIN (27)
#define SPI0_SSEL_PIN (28)
void SPI_Init(void) {
// 使能 SPI0 时钟
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 13); // 使能 SPI0 时钟
// 配置引脚
LPC_IOCON->P0_25 = (LPC_IOCON->P0_25 & ~0x0F) | 0x02; // 配置 P0.25 为 SPI0 MOSI
LPC_IOCON->P0_26 = (LPC_IOCON->P0_26 & ~0x0F) | 0x02; // 配置 P0.26 为 SPI0 MISO
LPC_IOCON->P0_27 = (LPC_IOCON->P0_27 & ~0x0F) | 0x02; // 配置 P0.27 为 SPI0 SCLK
LPC_IOCON->P0_28 = (LPC_IOCON->P0_28 & ~0x0F) | 0x02; // 配置 P0.28 为 SPI0 SSEL
// 配置 SPI0
LPC_SPI0->CR = 0x02; // 使能 SPI0,主模式
LPC_SPI0->CFG = 0x08; // 8 位数据长度
LPC_SPI0->BR = 0x00; // 设置波特率
}
void SPI_SendChar(char ch) {
while (!(LPC_SPI0->STAT & 0x02)); // 等待发送缓冲区为空
LPC_SPI0->TXDAT = ch; // 发送字符
}
char SPI_ReceiveChar(void) {
while (!(LPC_SPI0->STAT & 0x01)); // 等待接收缓冲区有数据
return LPC_SPI0->RXDAT; // 读取接收缓冲区中的数据
}
int main(void) {
// 初始化 SPI
SPI_Init();
// 发送数据
SPI_SendChar('H');
SPI_SendChar('e');
SPI_SendChar('l');
SPI_SendChar('l');
SPI_SendChar('o');
// 接收数据
char received_data = SPI_ReceiveChar();
while (1) {
// 主循环
}
}
5.3.5 SPI 通信协议
SPI 通信协议包括以下几个要素:
- 主从模式:主设备控制通信,从设备被动响应。
- 数据长度:数据帧中的数据位数,通常为 8 位。
- 时钟极性和相位:SCLK 的极性和相位,用于同步数据传输。
- 从设备选择:通过 SSEL 信号选择从设备。
5.3.6 SPI 性能优化
- 时钟频率优化:根据通信需求选择合适的时钟频率,提高通信速度。
- 数据缓冲优化:使用缓冲区管理数据流,减少数据溢出的风险。
- 中断处理优化:减少中断处理函数的执行时间,提高系统的响应速度。
5.4 I2C(内部集成电路总线)
5.4.1 I2C 基本原理
内部集成电路总线(I2C)是一种同步串行通信接口,用于主设备和从设备之间的通信。I2C 总线包括两条信号线:SDA(数据线)和 SCL(时钟线)。I2C 支持多主设备和多从设备,具有简单、可靠的通信特点。
5.4.2 I2C 寄存器
LPC1100 系列单片机的 I2C 寄存器主要包括以下几类:
- 控制寄存器(I2C0CONSET、I2C0CONCLR):用于配置 I2C 的工作模式,如主模式或从模式、启动和停止条件等。
- 状态寄存器(I2C0STAT):用于检测 I2C 的状态,如数据是否准备好、错误状态等。
- 数据寄存器(I2C0DAT):用于发送和接收数据。
- 配置寄存器(I2C0ADR、I2C0SCLH、I2C0SCLL):用于配置 I2C 的地址和时钟频率。
5.4.3 I2C 配置
I2C 的配置通常包括以下几个步骤:
- 配置 I2C 模式:选择主模式或从模式。
- 配置时钟频率:设置 I2C 的时钟频率。
- 配置设备地址:设置主设备或从设备的地址。
- 使能 I2C 模块:使能 I2C 模块并配置中断。
5.4.4 I2C 示例
5.4.4.1 初始化 I2C
以下示例代码展示了如何初始化 I2C0,配置其为主模式,并发送和接收数据:
#include "LPC11xx.h"
#define I2C0_SDA_PIN (23)
#define I2C0_SCL_PIN (24)
#define I2C0_DEVICE_ADDR (0x50) // 设备地址
void I2C_Init(void) {
// 使能 I2C0 时钟
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 16); // 使能 I2C0 时钟
// 配置引脚
LPC_IOCON->P0_23 = (LPC_IOCON->P0_23 & ~0x0F) | 0x02; // 配置 P0.23 为 I2C0 SDA
LPC_IOCON->P0_24 = (LPC_IOCON->P0_24 & ~0x0F) | 0x02; // 配置 P0.24 为 I2C0 SCL
// 配置 I2C0
LPC_I2C0->CONSET = 0x02; // 使能 I2C0,主模式
LPC_I2C0->ADR = I2C0_DEVICE_ADDR; // 设置设备地址
LPC_I2C0->SCLH = 0x04; // 设置 SCL 高电平时间
LPC_I2C0->SCLL = 0x0A; // 设置 SCL 低电平时间
LPC_I2C0->CONSET |= (1 << 6); // 使能 I2C0
}
void I2C_Start(void) {
// 发送启动条件
LPC_I2C0->CONSET |= (1 << 2); // 设置启动位
while (LPC_I2C0->STAT != 0x08); // 等待启动条件被识别
}
void I2C_Stop(void) {
// 发送停止条件
LPC_I2C0->CONCLR = (1 << 4); // 清除启动位
LPC_I2C0->CONSET |= (1 << 4); // 设置停止位
while (LPC_I2C0->STAT != 0x18); // 等待停止条件被识别
}
void I2C_SendByte(char data) {
// 发送一个字节
LPC_I2C0->DAT = data; // 设置数据寄存器
while (!(LPC_I2C0->CONSET & (1 << 5))); // 等待数据传输完成
LPC_I2C0->CONCLR = (1 << 5); // 清除数据传输完成标志
}
char I2C_ReceiveByte(void) {
// 接收一个字节
LPC_I2C0->CONSET |= (1 << 5); // 使能接收
while (LPC_I2C0->STAT != 0x50); // 等待数据准备好
char data = LPC_I2C0->DAT; // 读取数据寄存器
LPC_I2C0->CONCLR = (1 << 5); // 清除接收完成标志
return data;
}
void I2C_Write(char addr, char reg, char data) {
I2C_Start();
I2C_SendByte(addr << 1); // 发送目标设备地址,写模式
I2C_SendByte(reg); // 发送寄存器地址
I2C_SendByte(data); // 发送数据
I2C_Stop();
}
char I2C_Read(char addr, char reg) {
I2C_Start();
I2C_SendByte((addr << 1) | 1); // 发送目标设备地址,读模式
char data = I2C_ReceiveByte();
I2C_Stop();
return data;
}
int main(void) {
// 初始化 I2C
I2C_Init();
// 发送数据
I2C_Write(I2C0_DEVICE_ADDR, 0x01, 0x55); // 向地址 0x50 的设备的寄存器 0x01 写入 0x55
// 接收数据
char received_data = I2C_Read(I2C0_DEVICE_ADDR, 0x01); // 从地址 0x50 的设备的寄存器 0x01 读取数据
while (1) {
// 主循环
}
}
5.4.5 I2C 通信协议
I2C 通信协议包括以下几个要素:
- 主从模式:主设备控制通信,从设备被动响应。
- 设备地址:每个从设备在 I2C 总线上都有唯一的 7 位或 10 位地址。
- 数据长度:每次传输的数据长度通常为 1 到 32 位。
- 时钟频率:标准模式下 I2C 的时钟频率为 100 kHz,快速模式下为 400 kHz,高速模式下为 3.4 MHz。
- 启动和停止条件:主设备通过发送启动和停止条件来控制通信的开始和结束。
5.4.6 I2C 性能优化
- 时钟频率优化:根据通信需求选择合适的时钟频率,提高通信速度。
- 数据缓冲优化:使用缓冲区管理数据流,减少数据溢出的风险。
- 中断处理优化:减少中断处理函数的执行时间,提高系统的响应速度。
- 总线负载优化:合理安排总线上的设备,避免总线负载过重导致通信失败。
通过以上配置和示例代码,可以更好地理解和使用 LPC1100 系列单片机的 GPIO、UART 和 SPI 外设接口。这些接口在嵌入式系统中非常常见,掌握它们的配置和使用方法对于开发高效的嵌入式应用至关重要。希望这些内容对您的开发工作有所帮助。