| 本帖最后由 汉堡王 于 2023-9-10 20:19 编辑 
 7月份收到的追风剑STC32F12K54核心板,由于前段时间有点忙没来得及进行测试,正好这两天有时间就拿来测试一下
 
 STC32F12K54开发环境使用的是KeilC251,下寨地址在Keil的官网,不过下载的比较慢,可以到下面的地址去下载(https://blog.csdn.net/qq_34901073/article/details/82887681)
 C251可以与KeilC51安装到同一个文件夹下面:
 
 (默认是安装在C盘,建议改到D盘)
 
 
   
 安装完成之后还需要到STC-isp中添加Keil的头文件和型号信息,好的一点是软件上可以自动设置,只要自己选择路径就好了
 (不得不说STC—ISP的功能是越来越强大了,希望能越做越好!)
 
   
 完成这些之后基本的开发环境就算是配置完成了。还是挺简单的。
 
   
 这是我收到的STC32F12K54核心板(追风剑),为了方便测试,给它焊接了排针,不过焊接完最右下角的排针之后我发现复位键好像不能用了,
 不知道是不是焊接温度过高把复位按钮烫坏了,那个地方正好是GND,铜皮比较的厚,我烙铁功率不太行,接触了好一会才化锡,
 不过整体来说问题不大!
 后面又外接了一跟线去试,发现还是不太行,后面再研究研究!
 原本的里面是有一个LED流水灯的demo,正好对应的P2端口的8个引脚。
 
   
 使用官方的例程要将demo文件夹放在工程文件夹的上级目录,参照程序中的定义:
 
   
 这点还是挺方便的,不用将这些重复的文件每份工程都复制一遍了。
 
   
 此外,还可根据需要灵活的选择是驱动硬件的LED还是驱动调试接口LED-DIP64虚拟设备,这点挺不错的,方便在没有硬件条件的情况下进行实验。
 
 流灯的主函数里面初始化了相关的端口,然后根据前面VirtualDevice选择是硬件流水灯还是软件流水灯复制代码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;   //设置为准双向口
    usb_init(); //USB初始化
    ICacheOn(); //开启ICache
    Timer0_Init();
    EUSB = 1;   //IE2相关的中断位操作使能后,需要重新设置EUSB
    EA = 1;     //打开总中断
    while(1)
    {
        #if(VirtualDevice)
        SoftwareMarquee();
        #else
        HardwareMarquee();
        #endif
    }
}
 程序下载:
 开发文档提供了两种下载的思路,一种硬件复位,复位后判断P3^2引脚的状态,另外一种是软件复位,需要用到定时器,每隔一段时间判断一下P3^2引脚的转态,按下超过1秒就进入进入USB下载模式,
 在进入USB下载模式后,将用数据线连接核心板和电脑,
 进入USB下载模式前显示:
  ,此时可以使用虚拟USB串口和板子进行通信 进入USB下载模式后显示:
  ,此时进入程序下载 
 然后打开程序文件,配置好程序下载设置,然后点击
  进行程序下载。 下载完成之后会显示当前芯片的运行频率等等
 
   
 整个的操作还是方便的。
 
 
 定时器:
 
   
 STC32F12K54内置了5个24位的定时器,其中8位预分频和16位计数
 
 定时器配置:以定时器0为例,使用定时器模式0进行定时
 
 复制代码void Timer0_init(void)
{
        TR0 = 0;    //停止计数
    #if (Timer0_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
        #error "Timer0设置的中断过快!"
    #elif ((Timer0_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
        ET0 = 1;    //允许中断
    //  PT0 = 1;    //高优先级中断
        TMOD &= ~0x03;
        TMOD |= 0;  //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
    //  T0_CT = 1;  //计数
        T0_CT = 0;  //定时
    //  T0CLKO = 1; //输出时钟
        T0CLKO = 0; //不输出时钟
        #if (Timer0_Reload < 65536UL)
            T0x12 = 1;  //1T mode
            TH0 = (u8)((65536UL - Timer0_Reload) / 256);
            TL0 = (u8)((65536UL - Timer0_Reload) % 256);
        #else
            T0x12 = 0;  //12T mode
            TH0 = (u8)((65536UL - Timer0_Reload/12) / 256);
            TL0 = (u8)((65536UL - Timer0_Reload/12) % 256);
        #endif
        TR0 = 1;    //开始运行
    #else
        #error "Timer0设置的中断过慢!"
    #endif
}
  定时器输出频率计算公示,用输出逻辑分析仪大概的看了一下例程里面的波形,还是十分准确的 
 
   
 软件不好用波形不是很好看,凑合着看一下吧
  在开例程的时候我发现有2段代码一时间没看懂是干什么的,就是这个ICACHE,于是就查了一下手册,这里还有必要讲一下ICACHE功能:
 
   可以看出,这个ICACHE的作用就是匹配单片机的核心频率和ROM的速率的,不过使用的时候要注意关闭ICACHE之后才能操作EEPROM
 下面是开启ICACHE和关闭ICACHE的代码:
 
 
 USB虚拟串口调试:复制代码void ICacheOn(void)     //打开ICACHE功能
{
    bit fEA;
    
    if(WTST > 0)
    {
        fEA = EA;
        EA = 0;         //关闭中断,防止写触发命令序列中途产生中断
        _nop_();
        _nop_();
        TA = 0xaa;      //写入触发命令序列1
                        //此处不能有其他任何指令
        TA = 0x55;      //写入触发命令序列2
                        //此处不能有其他任何指令
        ICHECR = 0x01;  //写保护暂时关闭,可以修改ICHECR中的EN位
                        //EN为再次进入写保护状态
        _nop_();
        _nop_();
        EA = fEA;
    }
}
void ICacheOff(void)//关闭ICACHE功能
{
    bit fEA;
    fEA = EA;
    EA = 0;         //关闭中断,防止写触发命令序列中途产生中断
    _nop_();
    _nop_();
    TA = 0xaa;      //写入触发命令序列1
                    //此处不能有其他任何指令
    TA = 0x55;      //写入触发命令序列2
                    //此处不能有其他任何指令
    ICHECR = 0x00;  //写保护暂时关闭,可以修改ICHECR中的EN位
                    //EN位再次进入写保护状态
    _nop_();
    _nop_();
    EA = fEA;
}
 
 这个可以说是非常的方便了,以往的STM32下载和调试需要两根USB线,占用两个端口,而现在STC32F12K54内置了USB仿真和虚拟串口,功能十分的强悍!!!
 单精度浮点运算:
 
 通过USB虚拟串口显示。复制代码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_init();  //USB接口配置
    Timer0_Init();
    ICacheOn(); //开启ICache
    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();    //接收应答(固定格式)
        }
    }
}
 
   
 目前就测试了这些,后面还会继续更新,希望大家相互交流!
 
 |