这次来完成这两个题目
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);
- }
- }
运行效果
|