【灵动微电子MM32F5330测评】3.串口通讯+定时器

这次来完成这两个题目
 


UART,即通用异步接收器/发送器,是嵌入式开发中最常用的设备间通信协议之一,在开发中经常会用它来打印调试信息,可以最少使用2个引脚(TX和RX)实现数据传输(设备间需要共地),如果是单向传输可以只用一个引脚,开发板上已经实现了USB转UART的电路,使用引脚是PA9和PA10
 


使用串口涉及到GPIO复用功能,复用表可以在数据手册中找到
 


初始化串口,波特率设置为115200,停止位1,无校验,开启接收中断和空闲中断

复制

void uart_init(void)

{

    GPIO_InitTypeDef gpio_cfg;

    NVIC_InitTypeDef nvic_cfg;

    UART_InitTypeDef uart_cfg;



    RCC_APB2PeriphClockCmd(RCC_APB2Periph_UART1, ENABLE);

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);



    UART_StructInit(&uart_cfg);

    uart_cfg.BaudRate      = 115200;

    uart_cfg.WordLength    = UART_WordLength_8b;

    uart_cfg.StopBits      = UART_StopBits_1;

    uart_cfg.Parity        = UART_Parity_No;

    uart_cfg.HWFlowControl = UART_HWFlowControl_None;

    uart_cfg.Mode          = UART_Mode_Rx | UART_Mode_Tx;

    UART_Init(UART1, &uart_cfg);



    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_7);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_7);



    GPIO_StructInit(&gpio_cfg);

    gpio_cfg.GPIO_Pin   = GPIO_Pin_9;

    gpio_cfg.GPIO_Speed = GPIO_Speed_High;

    gpio_cfg.GPIO_Mode  = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOA, &gpio_cfg);



    gpio_cfg.GPIO_Pin  = GPIO_Pin_10;

    gpio_cfg.GPIO_Mode = GPIO_Mode_IPU;

    GPIO_Init(GPIOA, &gpio_cfg);



    nvic_cfg.NVIC_IRQChannel = UART1_IRQn;

    nvic_cfg.NVIC_IRQChannelPreemptionPriority = 0;

    nvic_cfg.NVIC_IRQChannelSubPriority = 1;

    nvic_cfg.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&nvic_cfg);



    UART_Cmd(UART1, ENABLE);

    UART_ITConfig(UART1, UART_IT_RX|UART_IT_RXIDLE, ENABLE);

}


中断函数处理,先实现将收到的数据原样返回的功能,创建接收缓冲区,通过接收中断向缓冲区写入数据,当触发空闲中断或缓冲区写入超过一半后,开始发送数据

复制

#define UART_BUFFER_LEN 50

uint8_t uart_buffer[UART_BUFFER_LEN] = {0};

uint8_t uart_rxindex = 0;

uint8_t uart_rxlen = 0;

uint8_t uart_txindex = 0;

uint8_t uart_txlen = 0;



void readrxtotxbuffer()

{

    uart_txlen += uart_rxlen;

    uart_rxlen = 0;

    UART_ITConfig(UART1, UART_IT_TX, ENABLE);

}



void UART1_IRQHandler(void)

{

    if(UART_GetITStatus(UART1, UART_IT_RX) == SET){

        UART_ClearITPendingBit(UART1, UART_IT_RX);

        uart_buffer[uart_rxindex++] = UART_ReceiveData(UART1);

        if(uart_rxindex == UART_BUFFER_LEN)

            uart_rxindex = 0;

        uart_rxlen++;

    }

    if(UART_GetITStatus(UART1, UART_IT_RXIDLE) == SET|| uart_rxlen == UART_BUFFER_LEN/2) {

        UART_ClearITPendingBit(UART1, UART_IT_RXIDLE);

        readrxtotxbuffer();

    }

    if(UART_GetITStatus(UART1, UART_IT_TX) == SET){

        UART_ClearITPendingBit(UART1, UART_IT_TX);

        if(uart_txlen > 0)

        {

            UART_SendData(UART1,uart_buffer[uart_txindex++]);

            if(uart_txindex == UART_BUFFER_LEN)

                uart_txindex = 0;

            uart_txlen--;

        }

        else

        {

            UART_ITConfig(UART1, UART_IT_TX, DISABLE);

        }

    }

}


运行效果
 


接下来实现将printf输出重定向到串口,方便打印调试信息,如果使用Keil开发的话可以很简单就实现,先勾选这个
 


然后添加下面这段代码

复制

int fputc(int ch, FILE *f)

{

    UART_SendData(UART1, ch);

    while (UART_GetFlagStatus(UART1, UART_FLAG_TXC) == RESET);

    return ch;

}

在main函数中测试printf输出

int main(void)

{

    led_init();

    keys_init();

    exit_init();

    uart_init();

    printf("This is printf test! %d",666);

    while (1)

    {

    }

}


运行效果
 


在开发中经常会有让某个特定任务按周期运行的需要,或者对输入信号进行计数,这时候就要用到定时器了,除此之外PWM也要用到定时器,接下来实现一个1s的定时器,MM32F5330拥有的定时器资源如下
 


接下来使用基础定时器6实现这个1秒的定时器,先看一下系统框图,Timer6在APB1上
 


系统初始化时默认180MHz的时钟频率,APB1不分频,这样将Timer6的预分频系数设置为18000-1,重载值设置为10000-1就得到了一个1s触发的定时器,代码如下

复制

void timer6_init(void)

{

    NVIC_InitTypeDef nvic_cfg;

    TIM_TimeBaseInitTypeDef timer_cfg;



    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);



    TIM_TimeBaseStructInit(&timer_cfg);

    timer_cfg.TIM_Prescaler         = (TIM_GetTIMxClock(TIM6) / 10000 - 1);

    timer_cfg.TIM_CounterMode       = TIM_CounterMode_Up;

    timer_cfg.TIM_Period            = (10000 - 1);

    timer_cfg.TIM_ClockDivision     = TIM_CKD_Div1;

    timer_cfg.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM6, &timer_cfg);



    TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);



    nvic_cfg.NVIC_IRQChannel = TIM6_IRQn;

    nvic_cfg.NVIC_IRQChannelPreemptionPriority = 0;

    nvic_cfg.NVIC_IRQChannelSubPriority = 1;

    nvic_cfg.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&nvic_cfg);



    TIM_Cmd(TIM6, ENABLE);

}


在中断中累加计数并发送

复制

uint8_t  sec_flag = 0;

uint32_t test_count = 0;



void TIM6_IRQHandler(void)

{

    if (RESET != TIM_GetITStatus(TIM6, TIM_IT_Update))

    {

        TIM_ClearITPendingBit(TIM6, TIM_IT_Update);

        test_count += 1;

        printf("sec count %d",test_count);

    }

}


运行效果

---------------------
作者:yuyy1989
链接:https://bbs.21ic.com/icview-3385032-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值