1. 简介:自己写此部分的程序即耗时,也不明智,因此,此篇**是关于移植和分析的**
2. 移植 uart 程序: 参照的程序是 红牛开发板/例程-Example/二、基础例程/ 下的有关 usart 部分
在做uart部分之前,需要参照之前章程搭建固件库和FreeRTOS工程,搭建完成之后,将上边目录下的 driver 中的 driver 中的delay.c、delay.h、USART.c、USART.h拷贝到 PROJ\uart 目录下,部分截图如下:
<img id="aimg_iRr9B" class="zoom" file="http://img.blog.csdn.net/20161130232329921" lazyloadthumb="1" border="0" alt="" /><img id="aimg_ftBcb" class="zoom" file="http://img.blog.csdn.net/20161130232402352" lazyloadthumb="1" border="0" alt="" />
在iar软件中,将新添加的两个 .c 文件放到usr目录下:
<img id="aimg_JB8Zv" class="zoom" file="http://img.blog.csdn.net/20161130232507462" lazyloadthumb="1" border="0" alt="" />
在包含进 .c 后还需要添加他们相应的 .h 文件的搜索路径:...PROJ\uart\driver
<img id="aimg_EZ4FP" class="zoom" file="http://img.blog.csdn.net/20161130232841865" lazyloadthumb="1" border="0" alt="" />
在程序中我们用到了 printf ,这个函数需要 Full 版本library 的支持:
<img id="aimg_eD0qW" class="zoom" file="http://img.blog.csdn.net/20161130233206170" lazyloadthumb="1" border="0" alt="" />
主函数 main.c
[cpp] view plain copy
print?<img id="aimg_c4xMd" class="zoom" width="12" height="12" file="https://code.csdn.net/assets/CODE_ico.png" border="0" alt="" /><img id="aimg_eE8SR" class="zoom" width="12" height="12" file="https://code.csdn.net/assets/ico_fork.svg" border="0" alt="" />
#include <stdio.h> #include &quot;misc.h&quot; /* Scheduler includes. */ #include &quot;FreeRTOS.h&quot; #include &quot;task.h&quot; #include &quot;queue.h&quot; #include &quot;USART.h&quot; #include &quot;delay.h&quot; #define LED_D1_ON() GPIO_ResetBits(GPIOF, GPIO_Pin_6) #define LED_D1_OFF() GPIO_SetBits(GPIOF, GPIO_Pin_6) static void LED_Init(void); static void LED_D1_Task(void *pvParameters); static void UART1_Task(void *pvParameters); int main(void) { LED_Init(); // 初始化 LED 引脚 USART1_Init(); Delay_Init(); Delay_ms(10); SendMessage(); printf(&quot;write by lip!\n\r&quot;); xTaskCreate(LED_D1_Task, &quot;LED_D1&quot;, 1000, NULL, 3, NULL); xTaskCreate(UART1_Task, &quot;UART1&quot;, 1000, NULL, tskIDLE_PRIORITY + 3, NULL); /* 启动调度器 */ vTaskStartScheduler(); while(1); return 0; } void LED_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); // 使能 GPIOF 的时钟 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOF, &GPIO_InitStructure); } void LED_D1_Task(void *pvParameters) { while ( 1 ) { LED_D1_ON(); vTaskDelay(500 / portTICK_RATE_MS); LED_D1_OFF(); vTaskDelay(500 / portTICK_RATE_MS); } } void UART1_Task(void *pvParameters) { while(1) { vTaskDelay(100 / portTICK_RATE_MS); if(data_length) { USART1_SendString(rx_buffer, data_length); data_length = 0; } } }
我们还需要在 usr 目录下 stm32f10x_it.c 中实现一下 usart 的中断入口,以便支持用户的输入:
在 void NMI_Handler(void) 函数上边添加:
[cpp] view plain copy
print?<img id="aimg_W7UU8" class="zoom" width="12" height="12" file="https://code.csdn.net/assets/CODE_ico.png" border="0" alt="" /><img id="aimg_x5EEE" class="zoom" width="12" height="12" file="https://code.csdn.net/assets/ico_fork.svg" border="0" alt="" />
void USART1_IRQHandler(void) { u8 res; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) // 接收到数据 { res = USART_ReceiveData(USART1); // 读取接收到的数据USART1->DR if(data_length < DATA_BUF_SIZE) { rx_buffer[data_length] = res; // 记录接收到的值 data_length++; } } }
当然 .h 中的声明不要忘记:
<img id="aimg_hnlCE" class="zoom" file="http://img.blog.csdn.net/20161130233817735" lazyloadthumb="1" border="0" alt="" />
至此,可以 make、下载了,用串口助手连接上串口一,在开机的瞬间会看到打印一串的数据,并等待用户输入,当用户输入时,会原封不动的打印出来。
<img id="aimg_TmXjC" class="zoom" file="http://img.blog.csdn.net/20161204192356334" lazyloadthumb="1" border="0" alt="" />
【1】为了尊重源作者,打印信息并没有大范围改动
3. 分析固件库中的 delay 延时: delay 函数的实现应用的是 m3 核的 systick,是一个硬件部分,一个 24 位的倒计数定时器,当倒计时到0值时会从LOAD寄存器装载新值,还有一点的是当enable不清零的情况,他的运作就不会停息
涉及到固件库中的结构体如下:
[cpp] view plain copy
print?<img id="aimg_Frq56" class="zoom" width="12" height="12" file="https://code.csdn.net/assets/CODE_ico.png" border="0" alt="" /><img id="aimg_UtNYQ" class="zoom" width="12" height="12" file="https://code.csdn.net/assets/ico_fork.svg" border="0" alt="" />
#define __IO volatile typedef struct { __IO uint32_t CTRL; /* Offset: 0x00 SysTick Control and Status Register */ __IO uint32_t LOAD; /* Offset: 0x04 SysTick Reload Value Register */ __IO uint32_t VAL; /* Offset: 0x08 SysTick Current Value Register */ __I uint32_t CALIB; /* Offset: 0x0C SysTick Calibration Register */ } SysTick_Type;
用于将首地址强制转化成此结构体,方便用户使用
SysTick寄存器说明如下:
【1】控制和状态寄存器 CTRL :
位段 |