coocox学习笔记-串口

来源:互联网 发布:淘宝贷款利息是多少 编辑:程序博客网 时间:2024/06/13 07:44

CoIDE版本:CoIDE-V2Beta

编译器版本:gcc-arm-none-eabi-5_2-2015q4

目标板:STM32F030C8T6

之前一直使用MDK开发STM32应用程序,近日想尝试下gcc编译STM32,享受下开源的果实,于是乎在网上了解到了coocox,它有一个CoIDE用来编辑代码,是简版的eclipse,目前最新版为V2Beta,之前用eclipse生成注释很方便,所以就想试试CoIDE是否也可以,但尝试了半天也没搞定,始终无法自动生成注释。。。

coocox使用的STM32库代码是cube库而不是std标准库,看来是紧跟ST的步伐那,还好之前也使用过cube库,更加方便了coocox的上手,在CoIDE上设置好编译器路径,这个在coocox的官网上有介绍,很简单。

创建好一个STM32F030C8T6的工程,在Repository页面上添加cmsis_core、STM32F030x8_CUBELIB组件,使用coocox必须要了解的一个概念是Components(组件),它把库,驱动,OS,启动代码等抽象为组件,使用时直接添加即可,同时在组件中也配有示例代码,本例创建了一个USART的工程,添加完组件后会在工程目录下产生一个components的目录,里面存放我们添加的组件文件,目前该工程为空工程,添加两个文件uart.c、uart.h文件,工程组织如下:


uart.c和uart.h文件是从之前学习cube库时使用的直接拷贝过来稍作修改即可,uart.c代码如下:

#include "UART.h"#include "stm32f0xx_hal_def.h"UART_HandleTypeDef uartHandle;uint8_t aRxBuffer[BUFFSIZE];uint8_t aTxBuffer[BUFFSIZE];struct uart uart_rev;void HAL_UART_MspInit(UART_HandleTypeDef *huart){  GPIO_InitTypeDef  GPIO_InitStruct;/*##-1- Enable peripherals and GPIO Clocks #################################*//* Enable GPIO TX/RX clock */USARTx_TX_GPIO_CLK_ENABLE();USARTx_RX_GPIO_CLK_ENABLE();/* Enable USART2 clock */USARTx_CLK_ENABLE(); /*##-2- Configure peripheral GPIO ##########################################*/  /* UART TX GPIO pin configuration  */GPIO_InitStruct.Pin       = USARTx_TX_PIN;GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull      = GPIO_NOPULL;GPIO_InitStruct.Speed     = GPIO_SPEED_HIGH;GPIO_InitStruct.Alternate = USARTx_TX_AF;HAL_GPIO_Init(USARTx_TX_GPIO_PORT, &GPIO_InitStruct);/* UART RX GPIO pin configuration  */GPIO_InitStruct.Pin = USARTx_RX_PIN;GPIO_InitStruct.Alternate = USARTx_RX_AF;HAL_GPIO_Init(USARTx_RX_GPIO_PORT, &GPIO_InitStruct);/*##-3- Configure the NVIC for UART ########################################*//* NVIC for USART2 */HAL_NVIC_SetPriority(USARTx_IRQn, 0, 1);HAL_NVIC_EnableIRQ(USARTx_IRQn);}/**  * @brief UART MSP De-Initialization   *        This function frees the hardware resources used in this example:  *          - Disable the Peripheral's clock  *          - Revert GPIO and NVIC configuration to their default state  * @param huart: UART handle pointer  * @retval None  */void HAL_UART_MspDeInit(UART_HandleTypeDef *huart){/*##-1- Reset peripherals ##################################################*/USARTx_FORCE_RESET();USARTx_RELEASE_RESET();/*##-2- Disable peripherals and GPIO Clocks #################################*//* Configure UART Tx as alternate function  */HAL_GPIO_DeInit(USARTx_TX_GPIO_PORT, USARTx_TX_PIN);/* Configure UART Rx as alternate function  */HAL_GPIO_DeInit(USARTx_RX_GPIO_PORT, USARTx_RX_PIN);/*##-3- Disable the NVIC for UART ##########################################*/HAL_NVIC_DisableIRQ(USARTx_IRQn);}/**********************************************************************函数:uart_init()函数作用:串口初始化参数:uint32_t BaudRate=========================串口波特率返回值:无上一版本:无当前版本:1.0作者:最后修改时间:2015-04-02说明: **********************************************************************/void uart_init(uint32_t BaudRate){        uartHandle.Instance        = USARTx;    uartHandle.Init.BaudRate   = BaudRate;    uartHandle.Init.WordLength = UART_WORDLENGTH_8B;    uartHandle.Init.StopBits   = UART_STOPBITS_1;    uartHandle.Init.Parity     = UART_PARITY_NONE;    uartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;    uartHandle.Init.Mode       = UART_MODE_TX_RX;        if(HAL_UART_Init(&uartHandle) != HAL_OK)    {        Error_Handler();    }uart_rev.front = aRxBuffer;uart_rev.rear = aRxBuffer;//两个指针指向相同的地址空间if(HAL_UART_Receive_IT(&uartHandle,(uint8_t*)aRxBuffer,1) != HAL_OK){Error_Handler();}}void Error_Handler(void){    while(1)    {            }}/**********************************************************************函数:uart_read()函数作用:从接收缓冲区中读取数据参数:uint8_t *fmt--------------------------------接收到的数据uint16_t time_out---------------------------超时时间返回值:0:读取到数据-1:没有读取到数据上一版本:无当前版本:1.0作者:最后修改时间:2015-04-08说明: **********************************************************************/int8_t uart_read(uint8_t *fmt, uint16_t time_out){while(time_out){if(uart_rev.front != uart_rev.rear){//如果队首指针和队尾指针不同表明缓冲区中有数据还未收取*fmt=*uart_rev.front;uart_rev.front++;if (uart_rev.front >= (aRxBuffer+BUFFSIZE))uart_rev.front = aRxBuffer;return 0;}time_out--;}return (int8_t)-1;}/**********************************************************************函数:uart_char()函数作用:发送一个字节数据参数:uint8_t *fmt--------------------------------接收到的数据返回值:上一版本:无当前版本:1.0作者:最后修改时间:2015-04-08说明: **********************************************************************/void uart_char(uint8_t fmt){uartHandle.Instance->TDR = fmt;while(!(uartHandle.Instance->ISR & USART_ISR_TXE));}void uart_send(uint8_t *fmt, uint16_t len){while(len){uart_char(*fmt);fmt++;len--;}return ;}/***********************************************************************************函数:fputc(int ch, FILE *f)功能:重载标准函数里面的输入输出函数参数:无版本:V0.0.0作者:备注:************************************************************************************/#if defined(UART_DEBUG)int fputc(int ch, FILE *f){USARTx->TDR = ch;while(!(USARTx->ISR & USART_ISR_TXE));return ch;}#endif/**  * @brief  UART error callbacks  * @param  UartHandle: UART handle  * @note   This example shows a simple way to report transfer error, and you can  *         add your own implementation.  * @retval None  */void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){}/**  * @brief  Tx Transfer completed callback  * @param  UartHandle: UART handle.   * @note   This example shows a simple way to report end of IT Tx transfer, and   *         you can add your own implementation.   * @retval None  */void HAL_UART_TxCpltCallback(UART_HandleTypeDef * huart){}/**  * @brief  Rx Transfer completed callback  * @param  UartHandle: UART handle  * @note   This example shows a simple way to report end of IT Rx transfer, and   *         you can add your own implementation.  * @retval None  */void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){/* Set transmission flag: trasfer complete*/uart_rev.rear++;//更新rear指针if(uart_rev.rear >= (aRxBuffer + BUFFSIZE))uart_rev.rear = aRxBuffer;HAL_UART_Receive_IT(huart,uart_rev.rear,1);}/******************************************************************************//*                 STM32L0xx Peripherals Interrupt Handlers                   *//*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  *//*  available peripheral interrupt handler's name please refer to the startup *//*  file (startup_stm32l0xx.s).                                               *//******************************************************************************//**  * @brief  This function handles UART interrupt request.    * @param  None  * @retval None  * @Note   This function is redefined in "main.h" and related to DMA stream   *         used for USART data transmission       */void USARTx_IRQHandler(void){  HAL_UART_IRQHandler(& uartHandle);}
uart.h代码如下:

#ifndef __UART_H__#define __UART_H__#include "stm32f0xx_hal.h"#include "stm32f0xx_hal_def.h"#include "stm32f0xx_hal_uart.h"#define UART_DEBUG//#undef UART_DEBUG#ifdef UART_DEBUG#include <stdio.h>#include <stdarg.h>#endifstruct uart{uint8_t *rear;//在中断函数中更改uint8_t *front;//在主循环中更改};#define USARTx                           USART1#define USARTx_CLK_ENABLE()              __USART1_CLK_ENABLE()#define USARTx_RX_GPIO_CLK_ENABLE()      __GPIOA_CLK_ENABLE()#define USARTx_TX_GPIO_CLK_ENABLE()      __GPIOA_CLK_ENABLE() #define USARTx_FORCE_RESET()             __USART1_FORCE_RESET()#define USARTx_RELEASE_RESET()           __USART1_RELEASE_RESET()/* Definition for USARTx Pins */#define USARTx_TX_PIN                    GPIO_PIN_9#define USARTx_TX_GPIO_PORT              GPIOA  #define USARTx_TX_AF                     GPIO_AF1_USART1#define USARTx_RX_PIN                    GPIO_PIN_10#define USARTx_RX_GPIO_PORT              GPIOA #define USARTx_RX_AF                     GPIO_AF1_USART1/* Definition for USARTx's NVIC */#define USARTx_IRQn                      USART1_IRQn#define USARTx_IRQHandler                USART1_IRQHandler#define BUFFSIZE 500void HAL_UART_MspInit(UART_HandleTypeDef * huart);void HAL_UART_MspDeInit(UART_HandleTypeDef * huart);void uart_init(uint32_t BaudRate);int8_t uart_read(uint8_t *fmt, uint16_t time_out);void uart_char(uint8_t fmt);void uart_send(uint8_t *fmt, uint16_t len);void Error_Handler(void);void USARTx_IRQHandler(void);#endif</span>
主函数稍作修改即可,由于在uart中已经定义了Error_Handler()方法,因此把main.c中的删掉并添加uart的初始化代码,如下

<span style="font-size:14px;">/* Add your application code here*/uart_init(115200);/* Infinite loop */while (1){uart_send("1234567890\r\n",12);HAL_Delay(500);}
编译并下载代码到目标板运行,结果如下:


运行正常。

串口正常以后,就在想在coocox中如何使用printf函数呢,即把printf函数重定向到串口上,刚好在coocox的组件中有一个组件为Retarget_printf,添加该组件到工程中,该组件中有一个printf.c文件,用户需要去实现PrintChar(char c)函数,我们把在uart.c文件中的fputc函数替换成PrintChar(char c)函数,如下:

#if defined(UART_DEBUG)void PrintChar(char c){USARTx->TDR = c;while(!(USARTx->ISR & USART_ISR_TXE));return;}#endif
在主函数中使用printf来打印信息,编译后发现一个错误,提示impure_ptr重复定义,在coocox官网中也有人遇到说是因为使用了标准的系统启动文件,在配置选项中勾选不使用标准的系统启动文件,如下:



再次编译提示位定义_init,在main.c文件中添加一个空的_init()函数,编译通过,下载运行,发现没有换行,如下:



0x0A字符没有输出,不得不说printf.c文件实现还是有些小问题的,解决办法是把"\r\n"放在最前面即可

while (1){printf("\r\n1234567890");HAL_Delay(500);}
此时输出的信息是正常的,同时我们也可以格式化输出字符或整型值,但目前printf.c文件不支持浮点型数据输出,可以查看printf.c文件如下:


这个问题,coocox官网上有说不使用printf.c文件而是使用C库实现。我想修改下printf.c文件应该也是可以的。输出整型值如下:


浮点数支持的话,自己动手修改printf.c文件貌似比较费时间,还是用C库吧,毕竟之前MDK都是用的C库也,在工程中移除Retarget_printf组件,添加C_library组件,里面有一个syscalls.c文件,提供给用户一个_write接口,由于在CoIDE中所有组件文件都是上锁的,因此我们在外部用文本编辑器修改syscalls.c文件的_write函数,把宏打开,如下

/*Low layer write(output) function*/__attribute__ ((used))int _write(int file, char *ptr, int len){#if 1     //user code example     int i;     (void)file;     for(i = 0; i < len; i++)     {        // UART_PutChar is user's basic output function        UART_PutChar(*ptr++);     }#endif    return len;}
用户需要实现UART_PutChar()方法,把之前uart.c文件中的PutChar()方法换个名字就行了。由于使用到了C库,因此在配置选项的Link页面勾选使用Nano C库,如下:


还要使能Print float选项,由于不再使用Retarget_printf组件,所以这里使用了标准的系统启动文件,同时把main.c文件中的_init()方法删掉了。

编辑主函数测试代码:

while (1){printf("\r\n1234567890");printf("\r\nvalue=%d,%X",100,100);printf("\r\nabc:%f",123.56);HAL_Delay(500);}
下载到目标板,运行,测试正常


至此,可以很方便地调试代码啦!



1 0