TKM32F499高性能MCU评估板试用之万事开头难,先点个灯来压压惊!-腾讯云开发者社区-腾讯云

콘텐츠

如下图所示,评估板长这个样子:

TKM32F499深圳市好钜润科技有限公司发行的一款高性能单片机,以上图片是基于TKM32F499的一款评估板,可以看到评估板上的资源那是相当的丰富了,而且还是白菜价,到手价仅需88元,不得不说实在是香,香在哪呢?咱们看看特点就知道了。

1、特点

1、IPS全视角液晶屏,阳光下可视度高;

2、高分辨率800*480;

3、超大存储空间:16MB的FLASH及8MB的RAM,可以运行复杂的界面程序;

4、采用高性能TK499芯片,240MHz,带FPU,支持硬件浮点运算;

5、USB方式下载,可以用USB更新程序,图标及字库;

6、带WIFI模块,支持无线显示,利于接入IoT物联网

7、提供丰富外设:串口、SPI、GPIO、USB,SDIO、五向按键、3路LED灯;

8、性价比高,88元包含了高性能M4芯片,16M FLASH与8M RAM及高分辨率TFT屏, 可以直接片上编程,比串口屏灵活,速度更快;

这么强大的一个评估板,直接套在我们的产品上简直就是天然的优势,但不知道开发起来难度大不大?

根据官方对评估板的介绍,用户不需要关心环境设置以及路径设置,所有的一切,他们都帮我们配置好了,所以我们只需要拿到程序的工程文件,直接就可以开始编写代码,其它一些特殊的说明直接查看资料包即可。

2、开发平台

那这款芯片用什么平台来进行开发呢?

这是我们熟悉的Keil5,编程风格和STM32是几乎是一样的。

想要让芯片工作起来,去驱动连接的外设,首先我们得了解芯片的一些规格,比如系统框图、引脚排列和引脚说明、存储器映射表,了解了这些以后,我们再去结合芯片的Datasheet去查询相应的寄存器以及注意事项,最后完成我们产品功能的软件编写。

3、TKM32F499芯片架构

以下是TKM32F499芯片系统框图,系统框图能让我们快速了解这款芯片包含哪些模块单元,以便于我们开发产品时进行选型。

可以看到,芯片基于ARM-ContexM4 FPU架构,我们来简单了解下:

ARM Cortex-M4处理器是由ARM专门开发的最新嵌入式处理器,在M3的基础上强化了运算能力,新加了浮点、DSP、并行计算等。

ARM-ContexM4 FPU处理器则是在此架构基础上单精度浮点单元(FPU),能够高效率处理较为复杂的浮点运算,如电机闭环控制、PID算法、快速傅里叶变换等。

TKM32F499支持的功能还是非常多的,除了常规的STM32上有的功能,还加了一个特色模块,比如TK80.

4、TKM32F499芯片管脚及排列说明

5、TKM32F499存储器映射表

6、TKM32F499测评程序编写步骤及程序解读

玩任何一个板子,先点个灯,后面就好办了,官方资料包里第一个例程GPIO_LED是让评估板上的LED以固定的频率进行闪烁,我们来看下原理图:

由于例程里没有使用PWM去驱动LED,所以直接高低电平就可以驱动它进行工作了。管脚接在PD8这个位置。

既然和STM32的编程方式一样,那么肯定是以下的流程:

1、初始化并使能RCC时钟

2、GPIO模式配置及初始化

3、使用GPIO

TKM32F499,官方已经写好相应的开发库了,我们拿来即用即可,编写这个例程,一共需要用到库文件里四个API,分别是:

void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint32_t GPIO_Pin);
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint32_t GPIO_Pin);

6.1 RCC_AHBPeriphClockCmd

RCC_AHBPeriphClockCmd用于配置系统的RCC时钟,只有时钟起来了,外设才能工作。打HAL_rcc.h可以看到,官方根据Datasheet已经写好了相应的地址。

这里我们要控制的外设是GPIOD,根据存储器映射图,我们可以看到GPIOD挂在AHB1总线下:

对应的,接下来看Datasheet关于RCC相关的章节关于这部分的描述:

我们需要把这个寄存器的第三位给使能了,那么GPIOD功能就可以正常使用了。

所以非常简单,我们只需要把这一位和RCC的AHB1外设时钟使能寄存器做一个或操作即可,来看看程序里是怎么写的:

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);

追进该函数的RCC_AHBPeriphClockCmd源码实现:

void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    RCC->AHB1ENR |= RCC_AHBPeriph;
  }
  else
  {
    RCC->AHB1ENR &= ~RCC_AHBPeriph;
  }
}

这里首先使用断言函数assert_param检查参数是否有效,主要是检查是否为非法地址。

接下来判断NewState参数,如果是ENABLE ,则与RCC->AHB1ENR置位,否则清除该位,NewState参数其实是一个枚举。

typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;

那么RCC->AHB1ENR是啥呢?追进定义看看:

#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< SRAM base address in the bit-band region */
#define AHB1PERIPH_BASE       (PERIPH_BASE + 0x00020000)
#define RCC_BASE              (AHB1PERIPH_BASE + 0x3800)
#define RCC                 ((RCC_TypeDef *) RCC_BASE)

这是将一个地址强制转换成一个结构体,STM32里也是这么做的,我们看看对应的结构体:

typedef struct
{
  __IO uint32_t CR;            /*!< RCC clock control register,                   Address offset: 0x00 */
  __IO uint32_t PLLCFGR;       /*!< RCC clock configuration register,             Address offset: 0x04 */
  __IO uint32_t CFGR;          /*!< RCC clock configuration register,             Address offset: 0x08 */
  __IO uint32_t CIR;           /*!< RCC clock interrupt register,                 Address offset: 0x0C */
  __IO uint32_t AHB1RSTR;      /*!< RCC AHB peripheral clock register,            Address offset: 0x10 */
  __IO uint32_t AHB2RSTR;      /*!< RCC AHB peripheral clock register,            Address offset: 0x14 */
  __IO uint32_t APB1RSTR;      /*!< RCC AHB peripheral clock register,            Address offset: 0x18 */
  __IO uint32_t APB2RSTR;      /*!< RCC AHB peripheral clock register,            Address offset: 0x1C */
  __IO uint32_t AHB1ENR;       /*!< RCC AHB peripheral clock register,            Address offset: 0x20 */
  __IO uint32_t AHB2ENR;       /*!< RCC AHB peripheral clock register,            Address offset: 0x24 */
  __IO uint32_t APB1ENR;       /*!< RCC APB1 peripheral clock enable register,    Address offset: 0x28 */
  __IO uint32_t APB2ENR;       /*!< RCC APB1 peripheral clock enable register,    Address offset: 0x2C */
  __IO uint32_t BDCR;          /*!< RCC Backup domain control register,           Address offset: 0x30 */
  __IO uint32_t CSR;           /*!< RCC clock control & status register,          Address offset: 0x34 */
  __IO uint32_t PLLLCDCFGR;   /*!< RCC clock configuration register 2,           Address offset: 0x38 */
  __IO uint32_t PLLDCKCFGR;       /*!< RCC clock configuration register 3,           Address offset: 0x3C */
} RCC_TypeDef;

对应结构体的成员即为RCC的地址,如果想详细了解它的配置,可以查看手册时钟章节。

RCC_AHBPeriph_GPIOD是一个宏

对应的值是0x0000008,也就是(1 << 3),所以得出结论,把这个宏作为参数传递进RCC_AHBPeriphClockCmd这个函数,在第二个函数写上ENABLE即可完成GPIOD使能RCC时钟的初始化,真香!所以很容易可以写出以下代码完成GPIOD使能时钟的配置:

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);

6.2 GPIO_Init

/**
* @brief  Initializes the GPIOx peripheral according to the specified
*   parameters in the GPIO_InitStruct.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that
*   contains the configuration information for the specified GPIO
*   peripheral.
* @retval : None
*/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)

这个函数用户GPIO(通用功能I/O)功能的初始化,与RCC一样,程序里也是定义了操作GPIO相关的结构体GPIO_TypeDef,以下是对应的一些寄存器:

typedef struct
{
  __IO uint32_t CRL;
  __IO uint32_t CRH;
  __IO uint32_t IDR;
  __IO uint32_t ODR;
  __IO uint32_t BSRR;
  __IO uint32_t BRR;
  __IO uint32_t LCKR;
       uint32_t RESERVED;
  __IO uint32_t AFRL;
  __IO uint32_t AFRH;
  __IO uint32_t CRH_EXT;
  __IO uint32_t BSRR_EXT;
  __IO uint32_t AFRH_EXT;
} GPIO_TypeDef;

详细可以看GPIO章节手册里对寄存器的描述:

对IO的管脚、速率、模式的设置,用的是GPIO_InitTypeDef这个结构体:

typedef struct
{
  uint32_t GPIO_Pin;
  GPIOSpeed_TypeDef GPIO_Speed;
  GPIOMode_TypeDef GPIO_Mode;
}GPIO_InitTypeDef;

GPIO_Pin用于设置管脚,对应的也是相应的宏:

#define GPIO_Pin_0                 ((uint16_t)0x0001)  /* Pin 0 selected */
#define GPIO_Pin_1                 ((uint16_t)0x0002)  /* Pin 1 selected */
#define GPIO_Pin_2                 ((uint16_t)0x0004)  /* Pin 2 selected */
#define GPIO_Pin_3                 ((uint16_t)0x0008)  /* Pin 3 selected */
#define GPIO_Pin_4                 ((uint16_t)0x0010)  /* Pin 4 selected */
#define GPIO_Pin_5                 ((uint16_t)0x0020)  /* Pin 5 selected */
#define GPIO_Pin_6                 ((uint16_t)0x0040)  /* Pin 6 selected */
#define GPIO_Pin_7                 ((uint16_t)0x0080)  /* Pin 7 selected */
#define GPIO_Pin_8                 ((uint16_t)0x0100)  /* Pin 8 selected */
#define GPIO_Pin_9                 ((uint16_t)0x0200)  /* Pin 9 selected */
#define GPIO_Pin_10                ((uint16_t)0x0400)  /* Pin 10 selected */
#define GPIO_Pin_11                ((uint16_t)0x0800)  /* Pin 11 selected */
#define GPIO_Pin_12                ((uint16_t)0x1000)  /* Pin 12 selected */
#define GPIO_Pin_13                ((uint16_t)0x2000)  /* Pin 13 selected */
#define GPIO_Pin_14                ((uint16_t)0x4000)  /* Pin 14 selected */
#define GPIO_Pin_15                ((uint16_t)0x8000)  /* Pin 15 selected */
#define GPIO_Pin_16              ((uint32_t)0x010000)  /* Pin 16 selected */
#define GPIO_Pin_17              ((uint32_t)0x020000)  /* Pin 17 selected */
#define GPIO_Pin_18              ((uint32_t)0x040000)  /* Pin 18 selected */
#define GPIO_Pin_19              ((uint32_t)0x080000)  /* Pin 19 selected */
#define GPIO_Pin_20              ((uint32_t)0x100000)  /* Pin 20 selected */
#define GPIO_Pin_21              ((uint32_t)0x200000)  /* Pin 21 selected */
#define GPIO_Pin_22              ((uint32_t)0x400000)  /* Pin 22 selected */
#define GPIO_Pin_23              ((uint32_t)0x800000)  /* Pin 23 selected */
#define GPIO_Pin_All             ((uint32_t)0xFFFFFF)  /* All pins selected */

GPIO_Speed是用于IO速率的配置,对应的是一个枚举:

typedef enum
{
  GPIO_Speed_10MHz = 1,
  GPIO_Speed_2MHz,
  GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;

GPIO_Mode是针对IO的模式进行配置,对应的是一个枚举

typedef enum
{
GPIO_Mode_AIN = 0x0,  //模拟输入
GPIO_Mode_IN_FLOATING = 0x04, //浮空输入
GPIO_Mode_IPD = 0x28,  //下拉输入
GPIO_Mode_IPU = 0x48,  //上拉输入
GPIO_Mode_Out_OD = 0x14,//通用开漏输出
GPIO_Mode_Out_PP = 0x10,//通用推挽输出
GPIO_Mode_AF_OD = 0x1C, // 复用开漏输出
GPIO_Mode_AF_PP = 0x18  //复用推挽输出
}GPIOMode_TypeDef;

在了解了以下知识点以后,针对LED管脚的配置,我们很快就能写出代码:

//1、定义GPIO初始化结构体变量
GPIO_InitTypeDef GPIO_InitStructure;
//2、初始化配置管脚
GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_8;
//3、初始化管脚速率
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//4、初始化管脚模式,配置为推挽输出模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//5、调用GPIO_Init完成IO的初始化
GPIO_Init(GPIOD, &GPIO_InitStructure);

6.3 GPIO_SetBits、GPIO_ResetBits

GPIO_SetBits和GPIO_ResetBits主要是对端口进行设置和清除,对应的是下面这个寄存器:

以下是两个函数的源代码:

/**
* @brief  Sets the selected data port bits.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bits to be written.
*   This parameter can be any combination of GPIO_Pin_x where
*   x can be (0..15).
* @retval : None
*/
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint32_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  if(GPIO_Pin>GPIO_Pin_15)GPIOE->BSRR_EXT=GPIO_Pin>>16;
	else
  GPIOx->BSRR = GPIO_Pin;
}
/**
* @brief  Clears the selected data port bits.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bits to be written.
*   This parameter can be any combination of GPIO_Pin_x where
*   x can be (0..15).
* @retval : None
*/
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint32_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  GPIOx->BRR = GPIO_Pin;
}

根据功能描述,很容易可以写出下列代码:

//给GPIOD的第八位
GPIO_SetBits(GPIOD, GPIO_Pin_8); //PC8输出高电平,点亮LED
//清除GPIOD的第八位
GPIO_ResetBits(GPIOD, GPIO_Pin_8);//PD8输出低电平,熄灭LED

以下是该Demo的源代码:

/****************************************Copyright (c)****************************************************
**
**
**
**--------------File Info---------------------------------------------------------------------------------
** File name:			main.c
** modified Date:  		2017-6-20
** Last Version:		V0.1
** Descriptions:		  main 函数调用
**
** 好钜润科技,芯片事业部----深圳龙华应用分部
*********************************************************************************************************/
#include "HAL_conf.h"
/********************************************************************************************************
**函数信息 :int main (void)
**功能描述 :
**输入参数 :
**输出参数 :
********************************************************************************************************/
int main(void)
{
	uint32_t  i;
	GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO初始化结构体变量
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
	//配置连接LED的GPIO为推挽输出模式
	GPIO_InitStructure.GPIO_Pin  =  GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOD, &GPIO_InitStructure);
	while(1)//无限循环
	{
		GPIO_SetBits(GPIOD, GPIO_Pin_8); //PC8输出高电平,点亮LED
		for(i=0;i<2000000;i++);//延时
		GPIO_ResetBits(GPIOD, GPIO_Pin_8);//PD8输出低电平,熄灭LED
		for(i=0;i<2000000;i++);//延时
	}
}

7、TKM32F499程序编译与下载

7.1 程序编译

和STM32一样,程序编译直接点击Keil软件上的编译即可,如果程序没有错误则会生成对应的bin文件。

7.2 程序烧录

TK499 支持 U 盘方式下载,无需借助下载器,一根 USB 线就能下载。

方法一:五向按键向上推,同时按一下复位(注意,松手时,先松复位,再松五向按键),然后点一下 KEIL 的下载程序的按钮就可以下载了。KEIL 不会提示是否下载完成,听到退出 U 盘的“叮咚”声就可以了。下载完成一般可以自动运行,如果没运行,可以按一下复位或者断电再上电就可以运行。

方法二:向上推,同时按一下复位就会进入程序下载模式,同样的也会弹出一个 U 盘,把 KEIL 工程目录下生成的 bin 程序拖进 U 盘就行,如下图。

如果是芯片第一次使用,需要先烧录一个 Bootloader。方法是:把五向按键向左推,同时再按一下复位就进入了 Bootloader 下载模式(注意,松开按键时,先松复位,再松五向按键)。这时会弹出一个 TK499 的 U 盘,把开发包压缩包里的 TK499_Bootloader.bin拖进去就行。(一般情况下开发板已经是烧好 Bootloader,此步可省略)

Bootloader 是一个重要的文件,以后会不断升级 Bootloader,用它可以通过 USB下载图片及字库。

注意:2019.10.1 前发布的程序,一般没把 flash_download.exe 下载程序工具放进工程文件夹里,所以用不了方法一来下载。当然你要自己添加也是很容易的,把这个小工具放到工程目录下,然后复制下面两行命令进去就行。

flash_download
..//@L.bin TK499_V2

8、运行结果

LED以固定频率进行闪烁:

最后,感谢淘宝客服小姐姐多送了一块带触摸的开发板给我:

TKM32F499评估板例程及资料下载

链接:https://pan.baidu.com/s/1xujEO4vJ7i7UUK7v_fGNgw
提取码:g1y2
요약하다
TKM32F499是深圳市好钜润科技有限公司推出的高性能单片机,配备IPS全视角液晶屏、16MB FLASH、8MB RAM、240MHz TK499芯片等丰富资源,售价仅88元。开发简便,无需环境设置,支持Keil5开发平台。芯片基于ARM Cortex-M4 FPU架构,具备丰富功能,如TK80模块。开发步骤包括了解芯片规格、编写程序等。评估板示例程序GPIO_LED演示LED闪烁,使用RCC_AHBPeriphClockCmd配置系统时钟,使GPIOD功能可用。开发库提供API函数,如GPIO_Init、GPIO_SetBits等,简化开发流程。