串口通信基本原理
处理器与外部设备通信的两种方式:
传输原理:数据各个位同时传输。
优点:速度快
缺点:占用引脚资源多
传输原理:数据按位顺序传输。
优点:占用引脚资源少
缺点:速度相对较慢
串行通信
按照数据传送方向,分为:
数据传输只支持数据在一个方向上传输
允许数据在两个方向上传输,但是,在某一时刻,只允许数
据在一个方向上传输,它实际上是一种切换方向的单工通信;
允许数据同时在两个方向上传输,因此,全双工通信是两个
单工通信方式的结合,它要求发送设备和接收设备都有独立
的接收和发送能力。
UART(通用异步收发器),单总线
常见的串行通信接口:
通信标准 | 引脚说明 | 通信方式 | 通信方向 |
UART (通用异步收发器) | TXD:发送端 RXD:接受端 GND:公共地 | 异步通信 | 全双工 |
单总线 (1-wire) | DQ:发送/接受端 | 异步通信 | 半双工 |
SPI | SCK:同步时钟 MISO:主机输入,从机输出 MOSI:主机输出,从机输入 | 同步通信 | 全双工 |
I2C | SCL:同步时钟 SDA:数据输入/输出端 | 同步通信 | 半双工 |
STM32F4XX目前最多支持8个UART,STM32F407一般是6个。
波特率设置;
常用的串口相关寄存器
USART_BRR波特率寄存器
串口配置的一般步骤
GPIO时钟使能:RCC_AHB1PeriphClockCmd();
② 引脚复用映射:
GPIO_PinAFConfig();
③GPIO端口模式设置:GPIO_Init(); 模式设置为GPIO_Mode_AF
④串口参数初始化:USART_Init();
⑤开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)
NVIC_Init();
USART_ITConfig();//使能中断
⑥使能串口:USART_Cmd();
⑦编写中断处理函数:USARTx_IRQHandler();
⑧串口数据收发:
void USART_SendData();//发送数据到串口,DR
uint16_t USART_ReceiveData();//接受数据,从DR读取接受到的数据
⑨串口传输状态获取:
FlagStatus USART_GetFlagStatus();
void USART_ClearITPendingBit();
以下是串口通信实验
串口配置函数
void My_Usart1_Init(void)
{
GPIO_InitTypeDef GPIO_Initer;
USART_InitTypeDef USART_Initer;
NVIC_InitTypeDef NVIC_Initer;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
GPIO_Initer.GPIO_Mode=GPIO_Mode_AF;
GPIO_Initer.GPIO_OType=GPIO_OType_PP;
GPIO_Initer.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;
GPIO_Initer.GPIO_PuPd=GPIO_PuPd_UP;
GPIO_Initer.GPIO_Speed=GPIO_Speed_100MHz;
GPIO_Init(GPIOA,&GPIO_Initer);
USART_Initer.USART_BaudRate=115200;
USART_Initer.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_Initer.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_Initer.USART_Parity=USART_Parity_No;
USART_Initer.USART_StopBits=USART_StopBits_1;
USART_Initer.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_Initer);
USART_Cmd(USART1,ENABLE);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_Initer.NVIC_IRQChannel=USART1_IRQn;
NVIC_Initer.NVIC_IRQChannelCmd=ENABLE;
NVIC_Initer.NVIC_IRQChannelPreemptionPriority=1;
NVIC_Initer.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_Initer);
}
中断服务函数
void USART1_IRQHandler(void)
{
u8 x;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
x=USART_ReceiveData(USART1);
USART_SendData(USART1,x);
}
}
主函数
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
My_Usart1_Init();
while(1);
}
运行视频:
串口通信
外部中断实验
EXTI线0~15:对应外部IO口的输入中断。
EXTI线16:连接到PVD输出。
EXTI线17:连接到RTC闹钟事件。
EXTI线18:连接到USB OTG FS唤醒事件。
EXTI线19:连接到以太网唤醒事件。
EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件。
EXTI线21:连接到RTC入侵和时间戳事件。
EXTI线22:连接到RTC唤醒事件。
每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。
IO口与中断线的映射关系
GPIOx.0映射到EXTI0
GPIOx.1映射到EXTI1
…
GPIOx.15映射到EXTI15
只能使用7个中断服务函数
外部中断线10~15分配一个中断向量,共用一个中断服务函数。
外部中断常用库函数
①void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex);
//设置IO口与中断线的映射关系
②void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
//初始化中断线:触发方式等
③ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
//判断中断线中断状态,是否发生
④void EXTI_ClearITPendingBit(uint32_t EXTI_Line);
//清除中断线上的中断标志位
⑤RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);//使能SYSCFG时钟
//这个函数非常重要,在使用外部中断的时候一定要先使能SYSCFG时钟
外部中断一般配置步骤
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
② 初始化IO口为输入。
GPIO_Init();
void SYSCFG_EXTILineConfig();
EXTI_Init();
NVIC_Init();
⑥ 编写中断服务函数。
EXTIx_IRQHandler();
EXTI_ClearITPendingBit();
以下是外部中断实验代码
配置函数
void Exit_Init(void)
{
NVIC_InitTypeDef NVIC_Initer;
EXTI_InitTypeDef EXTI_Initer;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
KEY_Init();
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource4);
EXTI_Initer.EXTI_Line=EXTI_Line4;
EXTI_Initer.EXTI_LineCmd=ENABLE;
EXTI_Initer.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_Initer.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&EXTI_Initer);
NVIC_Initer.NVIC_IRQChannel=EXTI4_IRQn;
NVIC_Initer.NVIC_IRQChannelCmd=ENABLE;
NVIC_Initer.NVIC_IRQChannelPreemptionPriority=1;
NVIC_Initer.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_Initer);
}
中断服务函数
void EXTI4_IRQHandler(void)
{
delay_ms(10);
if(KEY0==0)
{
LED1=!LED1;
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
主函数
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Exit_Init();
LED_Init();
delay_init(168);
LED1=0;
while(1);
}
运行视频:
外部中断