UART简介(通用异步收发器,通常称串口)
UART,是一种串行、异步、全双工的通信协议,在嵌入式领域应用的非常广泛。
UART作为异步串行通信协议的一种,工作原理是将传输数据的每个二进制位一位接一位地传输。在UART通信协议中信号线上的状态为高电平时代表‘1’,信号线上的状态为低电平时代表‘0’。比如使用UART通信协议进行一个字节数据的传输时就是在信号线上产生八个高低电平的组合。
数据通信方式和方向
串口协议帧
波特率:常见波特率有1200、2400、4800、9600、19200、38400、57600、115200等等
起始位和停止位:起始位由低电平表示,停止位是0.5、1、1.5位表示
有效数据位:5、6、7、8位,低位在前,高位在后
校验位:奇校验、偶校验、0校验、1校验、无校验
RX采样
UART框图
#include "debug.h"
/* 标准库需要的支持函数 */
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
};
FILE __stdout;
void _sys_exit(int x)
{
x = x;
}
/* 重定义fputc函数 */
int fputc(int ch, FILE *f)
{
while((USART1->SR & 0X40) == 0); //循环发送,直到发送完毕
USART1->DR = (uint8_t)ch;
return ch;
}
/******************************************************************************
* @brief 初始化串口1作为调试端口
*
* @param[in] bound_rate : 波特率
*
* @return 无
*
******************************************************************************/
void Debug_Init(uint32_t bound_rate)
{
/* GPIO端口设置 */
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//使能USART1时钟
/* 串口1对应引脚复用映射 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); //PA9复用为USART1_TX
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //PA10复用为USART1_RX
/* USART1端口配置 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9,PA10
/* USART1 初始化设置 */
USART_InitStructure.USART_BaudRate = bound_rate; //波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据位长
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
USART_Cmd(USART1, ENABLE); //使能串口
}
int main(void)
{
Debug_Init(115200);
while((USART1->SR & 0X40) == 0);
USART_SendData(USART1, 'A');
while((USART1->SR & 0X40) == 0);
USART_SendData(USART1, 'B');
while((USART1->SR & 0X40) == 0);
USART_SendData(USART1, '\r');
while((USART1->SR & 0X40) == 0);
USART_SendData(USART1, '\n');
printf("uart is ok\r\n");
while (1) {
;
}
}
Timer(定时器)---以TIM3为例
TIM计数模式
TIM框图
TIM相关参数
倍频因子(默认为2)
自动加载值设置为1000
预分频器设置为84,
TIM3挂载到APB1总线,APB1总线42Mhz,倍频为2,则CK_INT = 42Mhz * 2 / 84= 1Mhz,则TIM3在1秒内计数1M次(每次1us) 具体定时时间:t = 一次TIM3计数时间 * 自动加载值 = 1us * 1000 = 1 ms
main.c
LED_t gLed[3];
int main(void)
{
Debug_Init(115200);
Delay_Init();
printf("timer start\r\n");
/* 初始化3个板载LED */
LED_Init(&gLed[0], GPIOE, GPIO_Pin_5);
LED_Init(&gLed[1], GPIOE, GPIO_Pin_6);
LED_Init(&gLed[2], GPIOC, GPIO_Pin_13);
int i = 0;
while (1) {
printf("%d\r\n", i++);
Delay_Ms(1000);
// //打开所有的LED灯
// LED_On(&gLed[0]);
// LED_On(&gLed[1]);
// LED_On(&gLed[2]);
// Delay_Ms(1000);
// //关闭所有的LED灯
// LED_Off(&gLed[0]);
// LED_Off(&gLed[1]);
// LED_Off(&gLed[2]);
// Delay_Ms(1000);
}
}
#include "delay.h"
/******************************************************************************
* @brief 通用定时器3中断初始化
* 定时器溢出时间计算方法:Tout = ((arr + 1) * (psc + 1)) / Ft us.
* Ft = 定时器工作频率, 单位: Mhz
*
* @param[in] arr : 自动重装值
* @param[in] psc : 时钟预分频数
*
* @return 无
*
******************************************************************************/
void TIM3_Init(uint16_t arr, uint16_t psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3时钟
TIM_TimeBaseInitStructure.TIM_Prescaler = psc; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down; //向下计数模式
TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure); //初始化定时器3
}
/******************************************************************************
* @brief 初始化定时器延时函数,定时1us
*
* @param[in] 无
*
* @return 无
*
******************************************************************************/
int Delay_Init(void)
{
TIM3_Init(100 - 1, 84 - 1); //
return 0;
}
/******************************************************************************
* @brief 微秒级延时
*
* @param[in] us : 延时微秒数
*
* @return 无
*
******************************************************************************/
void Delay_Us(uint32_t us)
{
TIM3->ARR = us; //自动重载器
TIM3->CNT = TIM3->ARR; //计数器
TIM_Cmd(TIM3, ENABLE); //启动定时器
while (TIM3->CNT) {;} //等待延时时间到
TIM_Cmd(TIM3, DISABLE); //关闭定时器
}
/******************************************************************************
* @brief 毫秒级延时,不建议在OS中使用
*
* @param[in] us : 延时毫秒数
*
* @return 无
*
******************************************************************************/
void Delay_Ms(uint32_t ms)
{
for(int i = 0; i < ms; i++){
Delay_Us(1000);
}
}