追风剑-STC32F12K54测试:1,自带硬件USB仿真;2, 60MHz CPU主频;3,250MHz PWM ?
拿到了STC家的32位8051——追风剑-STC32F12K54-64MHz ! RMB2.3据说MCU内置3大亮点 “三角函数运算器,浮点运算器,250MHz-PWM”。当然上面的都是官方的“片面之词”,本着求真务实的本性,我得一个个测试下是不是骗我的哈哈。测试一:自带硬件USB在线仿真看到这个芯片支持三种仿真
这里写着支持串口仿真,USB仿真和SWD仿真,串口仿真需要串口线,SWD仿真需要LINK1D仿真器(也是下载器),这里选择最方便的USB仿真,只需要一个USB-typec的线就搞定了,硬件连线如下:
在看到官网的程序包里,第一个就是最直观的跑马灯功能,这里果断选择这个程序作为我们的测试程序。
但是打开这个工程之后需要注意的是这个工程是带HID功能的,他会占用P30,P31引脚,但是我们USB仿真也需要用到这个引脚,需要修改下代码才能作为仿真试用!!
如上这个工程目录里,一眼就看到了这个stc_usb_hid_32f.lib,所以这个工程需要手动的修改一下,删掉所有HID的部分,最终的代码如下所示:
#include "../comm/STC32F.h"//包含此头文件后,不需要再包含"reg51.h"头文件
#define MAIN_Fosc 22118400UL
void delay_ms(int ms);
void HardwareMarquee(void);
/******************** 主函数 **************************/
void main(void)
{
EAXFR = 1; //扩展寄存器(XFR)访问使能
RSTFLAG |= 0x04; //设置硬件复位后需要检测P3.2的状态选择运行区域,否则硬件复位后进入USB下载模式
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
EA = 1; //打开总中断
while(1)
{
HardwareMarquee();
}
}
void HardwareMarquee(void)
{
P20 = 0; //LED On
delay_ms(250);
P20 = 1; //LED Off
P21 = 0; //LED On
delay_ms(250);
P21 = 1; //LED Off
P22 = 0; //LED On
delay_ms(250);
P22 = 1; //LED Off
P23 = 0; //LED On
delay_ms(250);
P23 = 1; //LED Off
P24 = 0; //LED On
delay_ms(250);
P24 = 1; //LED Off
P25 = 0; //LED On
delay_ms(250);
P25 = 1; //LED Off
P26 = 0; //LED On
delay_ms(250);
P26 = 1; //LED Off
P27 = 0; //LED On
delay_ms(250);
P27 = 1; //LED Off
P26 = 0; //LED On
delay_ms(250);
P26 = 1; //LED Off
P25 = 0; //LED On
delay_ms(250);
P25 = 1; //LED Off
P24 = 0; //LED On
delay_ms(250);
P24 = 1; //LED Off
P23 = 0; //LED On
delay_ms(250);
P23 = 1; //LED Off
P22 = 0; //LED On
delay_ms(250);
P22 = 1; //LED Off
P21 = 0; //LED On
delay_ms(250);
P21 = 1; //LED Off
}
//========================================================================
// 函数: void delay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2022-6-3
// 备注:
//========================================================================
void delay_ms(int ms)
{
int i;
do{
i = MAIN_Fosc / 14000;//软件延时与程序指令延时参数(WTST)值有关
while(--i);
}while(--ms);
}
代码只保留了端口初始化,延时和LED来回闪烁的功能, 然后对工程进行下设置:
然后工程如上设置,那代码部分就设置完了,开始硬件部分配置:
1.将板子上的芯片制作为仿真芯片,先按下板子上的P32按钮,在按下电源键并松开,最后松开P32按钮,就可以再串口那栏看见HID的那一行了,没有的话手动安装下驱动~
2.设置仿真芯片
这里需要注意时钟1指向的时钟选择自己的代码工程里定义好的主时钟,我的代码是22.1184Mhz的时钟,一定要和代码匹配!!
3.等待制作完成
出现上述提示即为成功,可以关闭这个软件了。这里切记一定要给板子断一下电在进行后续操作!!
4.编译代码
代码0错误,0警告,没有问题
5.进入仿真模式:
可以看到上面已经进入了经典的仿真界面!!!!非常的华丽,可以像我一样在哪一行打个断点,在点击全速运行!
然后就可以看到板子上的灯会来回的流动一圈了,再点一次运行就会再动一次,然后就可以开始后面的开发之旅啦!!~祝各位小伙伴用的愉快
测试二:32位8051系统时钟真能跑到 64MHz 吗?
可以看到这个STC家的宣传的大字图上64MHz几个大字特别的醒目,要知道以前的STC最高速度不过48Mhz,这速度一下上涨了33%,有那么点不真实,为了验证他是不是在吹牛,这里咱必须得动手实测下看看!
可以看到STC32F的手册商还有这个非常经典的主时钟控制寄存器,因为使用的内部的IRC时钟,这多少M没有办法测量外部的晶振来得到,那么这里就可以用这个主时钟分频到引脚上直接输出,当然为了照顾下我们的示波器,这里直接用系统时钟四分频输出,可以直接看手册的这一张代码:(不确定系统时钟的时候就可以用这个办法测试!!!)
这里附上测试代码,方便大家复制下载:
void main()
{
EAXFR = 1; //使能访问 XFR
//CKCON 上电初始值为 0,无需设置
//WTST 在 ISP 下载时已自动设置,也无需设置
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
// MCLKOCR = 0x01; //主时钟输出到 P5.4 口
// MCLKOCR = 0x02; //主时钟 2 分频输出到 P5.4 口
MCLKOCR = 0x04; //主时钟 4 分频输出到 P5.4 口
// MCLKOCR = 0x84; //主时钟 4 分频输出到 P1.6 口
while (1);
}
可以看到代码选择了系统时钟4分频输出,输出引脚选择了P54端口,这里下载的时候选择64m的时钟开始测试:
下载完成后,示波器接到板子上:
再来看示波器的结果:
可以看到示波器上输出波形的频率是大约为16Mhz,这是四分频输出,那就是说系统时钟是16*4Mhz,确确实实是64MHZ!!!诚不欺我!
当然手册还写着后续能到500MHZ,这里浅浅的期待一下哈哈!
冲哥戏说:高达 500MHz 的 PWM时钟,32位8051 PWM时钟源
=====这难到是为未来的超高速STC32H准备的【500MHz CPU工作时钟】?
测试三:32位8051的PWM时钟源真能达到 250MHz 吗?
可以看到这个STC家的宣传的大字图上 250MHz-PWM 几个大字特别的醒目,最大64M的主频却能提供250M的时钟源!得试试!
在查阅了手册和论坛的多方数据之后发现,官方有大佬发了实测能到307.5M的PWM,远超宣传的250M时钟源。所以我也得按照这个基础来试试是不是真的能达到。
可以看到官方大佬提供的PWM的历程的时钟如上所示,最终实测能测到一个3.075M的PWM输出!
当然,那么问题来了,既然官方说HPLL的输入时钟可以为6~12Mhz,可他才配置了7.5M,是不是还能再高!所以这里我设置输入IRC为48,PCKI设置为4分频~那不就刚好12M的时钟给HPLL了吗{:lol:}在来个极限的HPLL的82倍频(倍频为52-82倍,具体数据如下)测试下,理论来说可以达到492M的PWM时钟源!!说干就干,代码如下:
int main()
{
ICacheOn(); //使能 ICACHE 功能
EAXFR = 1;
P0M0 = 0; P0M1 = 0;
P1M0 = 0; P1M1 = 0;
P2M0 = 0; P2M1 = 0;
P3M0 = 0; P3M1 = 0;
P4M0 = 0; P4M1 = 0;
P5M0 = 0; P5M1 = 0;
//选择 HPLL 输入时钟分频
USBCLK &= ~PCKI_MSK;
USBCLK |= PCKI_D4; //PLL 输入时钟 4 分频
//设置 HPLL 的除频系数
HPLLCR = HPLLDIV_82; //F_HPLL=48M/4*82/2=480M
//启动 HPLL
HPLLCR |= ENHPLL; //使能 HPLL
delay(); //等待 HPLL 时钟稳定
//选择 HSPWM/HSSPI 时钟
#if (HSCK_SEL == HSCK_MCLK)
CLKSEL &= ~HSIOCK; //HSPWM/HSSPI 选择主时钟为时钟源
#elif (HSCK_SEL == HSCK_PLL)
CLKSEL |= HSIOCK; //HSPWM/HSSPI 选择 PLL 输出时钟为时钟源
#else
CLKSEL &= ~HSIOCK; //默认 HSPWM/HSSPI 选择主时钟为时钟源
#endif
HSCLKDIV = 0; //HSPWM/HSSPI 时钟源不分频
HSPWMA_CFG = 0x03; //使能 PWMA 相关寄存器异步访问功能
PWMA_PS = 0x00; //PWMA_CC1/CC1N 高速 PWM 输出到 CC1/CC1N 口
//注意:PWMA_PS 不能使用异步方式进行读写
//通过异步方式设置 PWMA 的相关寄存器
WritePWMA((char)&PWMA_CCER1, 0x00);
WritePWMA((char)&PWMA_CCMR1, 0x00); //CC1 为输出模式
WritePWMA((char)&PWMA_CCMR1, 0x60); //OC1REF 输出 PWM1(CNT<CCR 时输出有效电平 1)
WritePWMA((char)&PWMA_CCER1, 0x05); //使能 CC1/CC1N 上的输出功能
WritePWMA((char)&PWMA_ENO, 0x03); //使能 PWM 信号输出到端口 P1.0/P1.1
WritePWMA((char)&PWMA_BKR, 0x80); //使能主输出
WritePWMA((char)&PWMA_CCR1H, 50>>8); //设置 PWM 占空比为 50 个 PWM 时钟
WritePWMA((char)&PWMA_CCR1L, 50);
WritePWMA((char)&PWMA_ARRH, 99>>8); //设置输出 PWM 的周期为 100 个 PWM 时钟
WritePWMA((char)&PWMA_ARRL, 99);
WritePWMA((char)&PWMA_DTR, 10); //设置互补对称输出 PWM 的死区
WritePWMA((char)&PWMA_CR1, 0x01); //开始 PWM 计数
while (1);
}话不多说,直接上测试结果:
可以看到输出频率还是非常准确的。虽然波形稍微有一点点失真,但是输出频率高了多多少少会有些问题,这里可以设置PWM的计数周期,将PWM速度降下来,这里我把PWMA_ARR寄存器设为999,也就是输出频率保持在491K左右再来看看
看这个图波形是不是就瞬间很完美了!!所以官方说的250M其实应该是内部多方测试最稳定的一个版本,但是实际上极限的输出的频率远高于此,当然这里其实也可以看出一个事情,这里的HPLL输出频率已经达到了48/4*82 = 984MHZ ,离1Ghz其实已经非常接近了啊!!!
当然上述部分均属于测试,远超官方推荐的频率,我们一般把这种称之为超频(和电脑的CPU一样都能超频,当然超频有风险,使用需谨慎),可以看到下图所示,其实手册建议的HPLL输出在312-496MHZ之间最好(这里切记HPLL的输入时钟最好为6-12Mhz之间),我们这里提供一个最稳定最好用的一个PWM的配置。。
1.首先确定主频
可以看到ISP软件里最大时钟是64Mhz,按照我的风格最大的不用,选倒数第二个最保守,所以这里这里我选择用60mhz的主频。
STC建议选择不调节,用出厂前就校准好的 60MHz
2.确定HPLL的参数首先主频是60M,按照手册说的HPLL输出最大最好不超496,那这里直接60/8*64 = 480M,这个参数就挺好,公因数很多可以分出很多频率的PWM出去{:lol:}(还留了16M缓冲的空间,所谓做人留一线日后好相见,这里留16M日后好升级哈哈),最后输入到PWM的时钟2分频一下就是240mhz。
3.代码编写一般的话,pwm如果对频率没有太大要求,我们都会往精度上提一提,一般分成2^8个档位以上,这里为了参数好看点实用性强一点直接配置为1000档,也就是PWMA_ARR为999。最终代码如下:<blockquote>
话不多说,直接上图,可以看到这个PWM的参数其实很完美!输出频率也是我们的理论值240M/1000= 240k
所以说这个PWM其实就完全没问题,非常nice!最终代码附件下载~
这 500MHz/2 后占空比是50% 的250MHz PWM时钟
=====搞 音频PWM发声, 冲哥是第一人 !
16位PWM 当16位用,当10位用,当8位用,当2~16位用
16位PWM 当8位用
16位PWM 当10位用
16位PWM 当16位用
HPLL输出频率超过800M/2,也就是PWM输入时钟超过400M,测试4个样品,两个样品PWM无输出
HPLL输出频率超过700M/2,也就是PWM输入时钟超过350M,测试4个样品均输出正常
HPLL的输入频率确实比我们原始定的规格【6~12M】的范围要宽,【2~16M】都可以
冲哥 威武。从流逝那购买的板子应该快到了,紧跟冲哥学。 追风剑-STC32F12K54-64MHz-LQFP48转DIP48核心功能实验板, CPU-60MHz:
有【硬件三角函数,硬件浮点】
sin/cos,270时钟/60 <= 4.5uS
sin/cos,32个时钟/60,大致 0.5uS
比运算能力 STC32F12K54-64I-LQFP48, 超过 STM32F103C8T6了
=====请冲哥测试下【硬件三角函数,硬件浮点】
追风剑-STC32F12K54-64MHz-LQFP48转DIP48核心功能实验板的演示程序中也有对应的演示程序
/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com-----------------------------------------*/
/* --- QQ:800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序 */
/*---------------------------------------------------------------------*/
/*************功能说明 **************
本例程基于STC32F核心转接板(追风剑)进行编写测试。
短按(50ms~1s)P3.2按钮一次,计算一次浮点数运算结果。
通过USB生成的CDC串口发送,使用电脑串口助手就能查看计算结果。
项目加载“STC32_FPMU_LARGE_V1.0.lib”库函数,则使用硬件浮点数单元进行浮点数运算;
项目不加载“STC32_FPMU_LARGE_V1.0.lib”库函数,则使用keil软件浮点数库进行浮点数运算;
通过示波器测量P01低电平时间可对比使用硬件浮点数单元与使用keil软件浮点数库进行浮点数运算所需的时间。
此外程序演示两种复位进入USB下载模式的方法:
1. 通过每1毫秒执行一次“KeyResetScan”函数,实现长按P3.2口按键触发MCU复位,进入USB下载模式。
(如果不希望复位进入USB下载模式的话,可在复位代码里将 IAP_CONTR 的bit6清0,选择复位进用户程序区)
2. 通过加载“stc_usb_cdc_32f.lib”库函数,实现使用STC-ISP软件发送指令触发MCU复位,进入USB下载模式并自动下载。
(注意:使用CDC接口触发MCU复位并自动下载功能,需要勾选端口设置:下次使用STC-HID接口进行ISP下载)
下载时, 选择时钟 60MHZ (用户可自行修改频率)。
******************************************/
#define PRINTF_HID //printf输出直接重定向到USB接口(包含usb.h前定义)
#include "../comm/STC32F.h"//包含此头文件后,不需要再包含"reg51.h"头文件
#include "../comm/usb.h" //USB调试及复位所需头文件
#include <math.h>
#include "stdio.h"
#include "intrins.h"
/*************本地常量声明 **************/
#define MAIN_Fosc 60000000UL//定义主时钟
/*************IO口定义 **************/
/*************本地变量声明 **************/
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#"; //设置自动复位到ISP区的用户接口命令
//P3.2口按键复位所需变量
bit Key_Flag;
bit Key_Short_Flag;
bit Key_Short_Function;
u16 Key_cnt;
float cfl1=3.9;
float cfl2=5.1;
float cfl3;
float cfl4;
float cfl5;
float cfl6;
float cfl7;
float cfl8;
float cfl9;
float cfl10;
/*************本地函数声明 **************/
void KeyScan(void);
void delay_ms(u8 ms);
/****************外部函数声明和外部变量声明 *****************/
/******************** 主函数 **************************/
void main(void)
{
EAXFR = 1; //扩展寄存器(XFR)访问使能
P0M1 = 0x00; P0M0 = 0x00; //设置为准双向口
P1M1 = 0x00; P1M0 = 0x00; //设置为准双向口
P2M1 = 0x00; P2M0 = 0x00; //设置为准双向口
P3M1 = 0x00; P3M0 = 0x00; //设置为准双向口
P4M1 = 0x00; P4M0 = 0x00; //设置为准双向口
P5M1 = 0x00; P5M0 = 0x00; //设置为准双向口
P6M1 = 0x00; P6M0 = 0x00; //设置为准双向口
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
//====== USB 初始化 ======
P3M0 &= ~0x03;
P3M1 |= 0x03;
IRC48MCR = 0x80;
while (!(IRC48MCR & 0x01));
USBCLK = 0x00;
USBCON = 0x90;
//========================
usb_init();//USB CDC 接口配置
EA = 1;
while(1)
{
delay_ms(1);
KeyScan(); //每毫秒检查一次按键状态
if(DeviceState != DEVSTATE_CONFIGURED)//等待USB完成配置
continue;
if(Key_Short_Function) //P3.2按键短按
{
Key_Short_Function = 0; //短按一次P3.2按键,计算一次浮点数运算
P01 = 0;
cfl3 = cfl1*cfl2;
cfl4 = cfl1/cfl2-cfl3;
cfl5 = cfl1*cfl2+cfl4;
cfl6 = cfl1/cfl2*sin(cfl5);
cfl7 = cfl1/cfl2*cos(cfl6);
cfl8 = cfl1/cfl2*tan(cfl7);
cfl9 = cfl1/cfl2*sqrt(cfl8);
cfl10 = cfl1/cfl2*atan(cfl9);
P01 = 1;
printf("cfl3=%f\r\n",cfl3); //CDC串口打印计算结果
printf("cfl4=%f\r\n",cfl4);
printf("cfl5=%f\r\n",cfl5);
printf("cfl6=%f\r\n",cfl6);
printf("cfl7=%f\r\n",cfl7);
printf("cfl8=%f\r\n",cfl8);
printf("cfl9=%f\r\n",cfl9);
printf("cfl10=%f\r\n",cfl10);
}
if (bUsbOutReady)
{
//USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度
usb_OUT_done(); //接收应答(固定格式)
}
}
}
//========================================================================
// 函数: void delay_ms(u8 ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2021-3-9
// 备注:
//========================================================================
void delay_ms(u8 ms)
{
u16 i;
do{
i = MAIN_Fosc / 14000;//软件延时与程序指令延时参数(WTST)值有关
while(--i);
}while(--ms);
}
//========================================================================
// 函数: void KeyScan(void)
// 描述: P3.2口按键长按1秒触发软件复位,进入USB下载模式。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2022-6-11
// 备注:
//========================================================================
void KeyScan(void)
{
if(!P32)
{
if(!Key_Flag)
{
Key_cnt++;
if(Key_cnt >= 1000) //连续1000ms有效按键检测
{
Key_Short_Flag = 0;
Key_Flag = 1; //设置按键状态,防止重复触发
USBCON = 0x00; //清除USB设置
USBCLK = 0x00;
IRC48MCR = 0x00;
delay_ms(10);
IAP_CONTR = 0x60; //触发软件复位,从ISP开始执行
while (1);
}
else if(Key_cnt >= 50)//50ms防抖
{
Key_Short_Flag = 1; //设置短按标志
}
}
}
else
{
if(Key_Short_Flag) //判断是否短按
{
Key_Short_Flag = 0; //清除短按标志
Key_Short_Function = 1;
}
Key_cnt = 0;
Key_Flag = 0;
}
}
跟着冲哥学习 追风剑USB仿真{:4_174:}
冲哥的讲解非常详细,我开始自己摸索不太顺利,跟冲哥学习一下就操作成功!谢谢冲哥!
页:
[1]