TKM32F499高性能MCU评估板试用之万事开头难,先点个灯来压压惊!

简介: TKM32F499高性能MCU评估板试用之万事开头难,先点个灯来压压惊!

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

640.png

640.png

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、开发平台

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

640.jpg

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


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

3、TKM32F499芯片架构

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

640.jpg

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


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


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


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


640.jpg

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

640.jpg

5、TKM32F499存储器映射表

640.png

640.png

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

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

640.png

由于例程里没有使用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已经写好了相应的地址。

640.png

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

640.png

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

640.png

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

640.png

所以非常简单,我们只需要把这一位和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的地址,如果想详细了解它的配置,可以查看手册时钟章节。

640.png

640.png

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章节手册里对寄存器的描述:

640.png

对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主要是对端口进行设置和清除,对应的是下面这个寄存器:

640.png

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

/**
* @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 程序编译

640.png

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

7.2 程序烧录

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


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


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

640.png

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


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

640.png

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

flash_download
..//@L.bin TK499_V2

640.png

8、运行结果

LED以固定频率进行闪烁:

640.jpg

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

640.png

640.png

640.png

TKM32F499评估板例程及资料下载

链接:https://pan.baidu.com/s/1xujEO4vJ7i7UUK7v_fGNgw
提取码:g1y2

或者后台回复TK499即可获取。

往期精彩

网红物联网开发板小熊派使用评测


开源STM32产品:无线点菜宝使用评测


超轻量级网红软件定时器multi_timer(51+stm32双平台实战)

目录
相关文章
|
25天前
|
关系型数据库 芯片
ovp过压过流保护芯片,大电流限流,高压,选型大齐全
本文介绍了过压保护(OVP)和过流限流保护(OCP)的基本概念及其应用场景,如蓝牙耳机、充电宝等。文中推荐了几款平芯微的OVP/OCP保护芯片,包括单OVP芯片PW1600、W2609A、PW2605,以及OVP和OCP二合一的PW1605、PW1558A、PW1515等,详细列出了各芯片的主要特点和适用范围。
ovp过压过流保护芯片,大电流限流,高压,选型大齐全
|
6月前
|
芯片 关系型数据库
工程师首选:USB过压保护OVP芯片,40V-70V耐压,电流0.5A-6A
平芯微推出一系列集成保护功能的电源管理芯片,包括PW2605、PW2606B、PW2606、PW2609A、PW1600、PW1515、PW1605、PW1558A、PW2601、PW1555A、PW4054H、PW4057H和PW4056HH。这些芯片具备输入过压关闭保护,防止高压输入损坏电路,并提供不同电流等级的输出支持,部分型号还具有可调限流和内置LDO功能。产品适用于各种应用场景,如磁吸充电线、锂电池充电等。其中,PW系列芯片的过压保护点可调,且部分型号具有高耐压特性,以增强系统安全性。
|
7月前
|
传感器 数据采集 人工智能
LabVIEW FPGA开发实时滑动摩擦系统
LabVIEW FPGA开发实时滑动摩擦系统
48 0
|
7月前
|
数据采集 存储 传感器
LabVIEW开发监控聚变实验脉冲电源
LabVIEW开发监控聚变实验脉冲电源
34 0
|
7月前
|
存储 小程序 中间件
单片机中MCU跑RTOS相比裸机的优势
单片机中MCU跑RTOS相比裸机的优势
75 1
|
监控 芯片 计算机视觉
集成 NVDC 电源路径管理的1-4节电池升降压充电IC解决方案
描述 MP2760是一款集成窄电压DC(NVDC)电源路径管理功能和USB On-the-Go(OTG)功能的升降压充电IC,兼容USB PD,适用于单节至4节串联的电池包应用。该芯片的充电输入电压范围广,可支持最高22V。 当启用电池放电模式(Source mode)时,芯片的IN引脚可提供高达21V的电压。当提供电源输入时,MP2760 通过3个充电阶段为电池充电:恒流(CC)涓流充电和恒流(CC)预充、恒流(CC)快充或恒压(CV)充电。 MP2760 具有充电截止功能和自动充电功能,另外还提供了输入电流限制和最小输入电压(VIN)限功能,以防止输入源出现过载。MP2760 集成了
108 1
|
7月前
|
物联网 芯片
STC51单片机-应用系统并行扩展电路设计(存储器扩展)-物联网应用系统设计
STC51单片机-应用系统并行扩展电路设计(存储器扩展)-物联网应用系统设计
122 0
|
算法 数据可视化 前端开发
第三代软件开发-全新波形抓取算法
欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。 在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。 在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资
|
异构计算
1FPGA模型计算机整体方案设计【FPGA模型机课程设计】
1FPGA模型计算机整体方案设计【FPGA模型机课程设计】
79 0
|
机器学习/深度学习 算法 异构计算
Xilinx Zynq7035算力指标
本文介绍广州星嵌DSP C6657+Xilinx Zynq7035平台下Xilinx Zynq7035算力指标。
Xilinx Zynq7035算力指标