UART、TIMER

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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值