资讯详情

51单片机-宏晶STC与硬仿真

内容包括STC单片机内部硬件介绍(寄存器),STC15F硬仿真及其错误处理,MCS-51仿真介绍。紫色文字是超链接,点击自动跳转到相关博客。不断更新,原创不容易!

目录:

1)定时器Timer 2)辅助功能寄存器AUXR 3)中断寄存器

1)bit和sbit都是C51扩展的变量类型 2)bit位标量 3)sfr特殊功能寄存器

4)sbit 可定义可位搜索对象 5)sbit可录址位 6)bdata

三、Keil软件安装

1)前言 2)通过STC-ISP查看数据 3)通过USB转TTL查看数据

1)管脚排布

2)模拟使用方法

(1)安装Keil模拟驱动版本 (2)在Keil中创建项目 (3)项目设置,选择STC仿真驱动

(4)创建仿真芯片 (5)开始模拟 (6)硬件仿真显示支持新的寄存器SFR

1)Keil软件硬仿真 2)切换串口位置

1)显示Connect to target system lost

-----------------------------------------------------------------------------------------------------------------

STC单片机内部集成MAX810专用复位电路。PWM,8路高速10位A/D 转换,针对电机控制,强干扰场合。

本文涉及的硬仿真是基于IAP15F2K61S2作说明,STC15系列包含STC15F4K60S4系列、STC15F2K60S2系列、STC15F1K28AD系列、STC15F412AD系列、STC15F204AD系列、STC15F204SW系列、STC15F104S系列以及STC15F104W系列,不包含STC15F204EA系列与STC15F104E系列。

-----------------------------------------------------------

STC单片机的ISP(在系统可编程)/IAP(可编程应用)无需专用编程器,无需专用仿真器,可通过串口(P3.0/P3.1)直接下载用户程序。详细介绍移动STC_ISP总结和解决软件问题。

通过STC单片机软复位连续电下载程序:

原理:先测试STC-ISP下载软件发布的串口命令,打开程序中的串口中断,中断接收下载命令执行单片机复位命令,程序自动下载,整个过程不断电,无需操作复位按钮,下载过程无需触摸硬件。

图1 下载最低波特率9600

图2   接收波特率9600

接收波特率9600,接收到的连续数据为7F,接收波特率不同,结果也会不一样。知道了STC-ISP软件下发的数据,我们程序开启串口接收中断,判断接收的数据如果是这里7F,让单片机执行一条复位命令,程序就下载进去了。

#include "STC15W4K.H"      // 包含 "STC15W4K.H"寄存器定义头文件

unsigned  char num=0;       // 存放接收到的1个字节的数据

void delay500ms(void)

{

   unsigned char i,j,k;

  for(i=93;i>0;i--)     //注意后面没分号

  for(j=235;j>0;j--)    //注意后面没分号

  for(k=125;k>0;k--);    //注意后面有分号

}

void UART_init(void)

{

    // 下面代码设置定时器2

    T2H  = 0xFD;  //波特率:9600 /22.1184MHZ,1T

    T2L  = 0xC0;  //波特率:9600 /22.1184MHZ,1T

    AUXR = 0x15;    // 0001 0101,T2R=1启动T2运行,T2x12=1,定时器2按1T计数,S1ST2=1

    // 下面代码设置定串口1

    SCON = 0x50;  // 0101 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允许接收)

    // 下面代码设置中断

    ES   = 1;     //开串口1中断

    EA   = 1;     //开总中断

}

void main()

{

    UART_init();

    P00=0;

    delay500ms();

    P00=1;

    while(1)

    {

       P01=!P01;

       delay500ms();

    }

}

void UART1(void) interrupt 4 // 串行口1中断函数

{

    if(TI)

    {

       TI = 0;

    }

    if(RI)

    {

       RI = 0;

       num = SBUF;

       if (num==0x7F)  

       {

           IAP_CONTR   =    0x60;   //0110,0000  软复位到系统ISP监控区

       }      

    }

}

-----------------------------------------------------------

1)定时器Timer

PCA(可编程计数器阵列Programmable Counter Array)模块可再实现4个16位定时器,提供增强的定时器功能,与标准8051计数器/定时器相比,它需要较少的CPU干预。IAP15F2K61S2单片机的定时器向下兼容STC12C5608AD。

TCON与TMOD寄存器:

定时时间计算:也可以使用单片机小精灵

--------------------------------

2)辅助功能寄存器AUXR

--------------------------------

3)中断寄存器

-----------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------

中断查询次序号就是中断号,例如:

void  Int0_Routine(void) interrupt 0;

void  Timer0_Routine(void) interrupt 1;

void  Int1_Routine(void) interrupt 2;

void  Timer1_Routine(void) interrupt 3;

void  UART1_Routine(void) interrupt 4;

void  ADC_Routine(void) interrupt 5;

void  LVD_Routine(void) interrupt 6;

void  PCA_Routine(void) interrupt 7;

void  UART2_Routine(void) interrupt 8;

void  SPI_Routine(void) interrupt 9;

void  Int2_Routine(void) interrupt 10;

void  Int3_Routine(void) interrupt 11;

void  Timer2_Routine(void) interrupt 12;

void  Int4_Routine(void) interrupt 16;

void  S3_Routine(void) interrupt 17;

void  S4_SPI_Routine(void) interrupt 18;

void  Timer3_Routine(void) interrupt 19;

void  Timer4_Routine(void) interrupt 20;

-----------------------------------------------------------

一般出现在C51单片机编程中,一般程序中需要使用到空指令_nop_();字符循环移位指令_crol_;整数循环_irol_ _testbit测试并清零位(相当于8051 JBC 指令)等时使用。

-----------------------------------------------------------

Flash相对单片机里的RAM属于外部存取器,虽其结构位置装在单片机中,其实xdata是放在相对RAM的外面,而flash正是相对RAM外面。

int a 变量定义在内部RAM中,

xdata int a 定义在外部RAM或flash中,uchar code a 定义在flash中。

uchar code duma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40,0x00}; 

//共阴的数码管段选,P2口要取的数值

若定义 uchar aa[5],aa[5]中的内容是存放在数据存储区(RAM)中的,在程序运行工程中各个数组元素的值可以被修改,掉电后aa[5]中的数据无法保存。

若定义 uchar code bb[5]中的内容是存放在程序存储区(如flash)中的,只有在烧写程序时,才能改变bb[5]中的各元素的值,在程序运行工程中无法修改,并且掉电后bb[5]中的数据不消失。

-----------------------------------------------------------

1)bit和sbit都是C51扩展的变量类型

bit和int char之类的差不多,只不过char=8位, bit=1位而已。都是变量,编译器在编译过程中分配地址。除非你指定,否则这个地址是随机的。这个地址是整个可寻址空间,RAM+FLASH+扩展空间。bit只有0和1两种值,意义有点像Windows下VC中的BOOL。

sbit是对应可位寻址空间的一个位,可位寻址区:20H~2FH。一旦用了sbi xxx = REGE^6这样的定义,这个sbit量就确定地址了。sbit大部分是用在寄存器中的,方便对寄存器的某位进行操作的。

--------------------------------

2)bit位标量

bit位标量是C51编译器的一种扩充数据类型,利用它可定义一个位标量,但不能定义位指针,也不能定义位数组。它的值是一个二进制位,不是0就是1,类似一些高级语言中的Boolean类型中的True和False。

--------------------------------

3)sfr特殊功能寄存器

sfr也是一种扩充数据类型,点用一个内存单元,值域为0~255。利用它可以访问51单片机内部的所有特殊功能寄存器。如用sfr P1 = 0x90这一句定P1为P1端口在片内的寄存器,在后面的语句中我们用以用P1 = 255(对P1端口的所有引脚置高电平)之类的语句来操作特殊功能寄存器。

sfr P1 = 0x90; //定义P1 I/O 口,其地址90H

sfr 关键定后面是一个要定义的名字,可任意选取,但要符合标识符的命名规则,名字最好有一定的含义如P1 口可以用P1 为名,这样程序会变的好读好多.等号后面必须是常数,不允许有带运算符的表达式,而且该常数必须在特殊功能寄存器的地址范围之内(80H-FFH)。

sfr 是定义8 位的特殊功能寄存器而sfr16 则是用来定义16 位特殊功能寄存器,如8052 的T2 定时器,可以定义为:

sfr16 T2 = 0xCC; //这里定义8052 定时器2,地址为T2L=CCH,T2H=CDH

用sfr16 定义16 位特殊功能寄存器时,等号后面是它的低位地址,高位地址一定要位于物理低位地址之上.注意的是不能用于定时器0和1 的定义。

sfr是KEIL中用来定义硬件寄存器地址的关键字,具有定义硬件特性。举个例子: sfr P0 =0x80 (C语言,这样就定义了51系列MCU中0x80地址,在编程时可以用P0符号代替地址0x80,具有定义硬件特性)

--------------------------------

4)sbit 可定义可位寻址对象

如访问特殊功能寄存器中的某位.其实这样应用是经常要用的,如要访问P1 口中的第2 个引脚P1.1.我们可以照以下的方法去定义:

(1)sbit 位变量名=位地址

sbit P1_1 = 0x91;

这样是把位的绝对地址赋给位变量.同sfr 一样sbit 的位地址必须位于80H-FFH 之间.

(2)sbit 位变量名=特殊功能寄存器名^位位置

sft P1 = 0x90;

sbit P1_1 = P1 ^ 1; //先定义一个特殊功能寄存器名再指定位变量名所在的位置,当可寻址位位于特殊功能寄存器中时可采用这种方法

(3)sbit 位变量名=字节地址^位位置

sbit P1_1 = 0x90 ^ 1;

这种方法其实和2 是一样的,只是把特殊功能寄存器的位址直接用常数表示. 在C51存储器类型中提供有一个bdata 的存储器类型,这个是指可位寻址的数据存储器,位于单片机的可位寻址区中,可以将要求可位录址的数据定义为bdata,如:

unsigned char bdata ib; //在可位录址区定义ucsigned char 类型的变量ib

int bdata ab[2]; //在可位寻址区定义数组ab[2],这些也称为可寻址位对象

sbit ib7=ib^7 //用关键字sbit 定义位变量来独立访问可寻址位对象的其中一位

sbit ab12=ab[1]^12;

操作符"^"后面的位位置的最大值取决于指定的基址类型,char0-7,int0-15,long0-31.sfr 并标准C 语言的关键字,而是Keil 为能直接访问80C51 中的SFR 而提供了一个新的关键词,其用法是:

sfrt 变量名=地址值。

符号P1_0 来表示P1.0 引脚。在C 语言里,如果直接写P1.0,C 编译器并不能识别,而且P1.0 也不是一个合法的C语言变量名,所以得给它另起一个名字,这里起的名为P1_0,可是P1_0 是不是就是P1.0呢?你这么认为,C 编译器可不这么认为,所以必须给它们建立联系,这里使用了Keil C的关键字sbit 来定义,sbit 的用法有三种:

第一种方法:sbit 位变量名=地址值

第二种方法:sbit 位变量名=SFR 名称^变量位地址值

第三种方法:sbit 位变量名=SFR 地址值^变量位地址值

如定义PSW 中的OV 可以用以下三种方法:

sbit OV=0xd2   1说明:0xd2 是OV 的位地址值

sbit OV=PSW^2  2说明:其中PSW 必须先用sfr 定义好

sbit OV=0xD0^2 3说明:0xD0 就是PSW 的地址值

因此这里用sfr P1_0=P1^0;就是定义用符号P1_0 来表示P1.0 引脚,如果你愿意也可以起P10 一类的名字,只要下面程序中也随之更改就行了。

--------------------------------

4)sfr16 16位特殊功能寄存器

sfr16占用两个内存单元,值域为0~65535。sfr16和sfr一样用于操作特殊功能寄存器,所不同的是它用于操作占两个字节的寄存器,如定时器T0和T1。

--------------------------------

5)sbit可录址位

sbit同位是C51中的一种扩充数据类型,利用它可以访问芯片内部的RAM中的可寻址位或特殊功能寄存器中的可寻址位。如先前我们定义了

sfr P1 = 0x90; //因P1端口的寄存器是可位寻址的,所以我们可以定义

sbit P1_1 = P1^1; //P1_1为P1中的P1.1引脚

//同样我们可以用P1.1的地址去写,如sbit P1_1 = 0x91;

这样我们在以后的程序语句中就可以用P1_1来对P1.1引脚进行读写操作了。通常这些可以直接使用系统提供的预处理文件,里面已定义好各特殊功能寄存器的简单名字,直接引用可以省去一点时间,我自己是一直用的。当然您也可以自己写自己的定义文件,用您认为好记的名字。

--------------------------------

6)bdata

将变量定义在可位寻址片内数据存储区,允许位与字节混合访问。

-----------------------------------------------------------

STC MCU都具有唯一的MCU ID号,一般保存在RAM的0xF1-F7区域,对于15系列,同时会保存在ROM的最后7个字节中。因此,可以通过字符指针,获取MCU ID值,用于程序的加密。

// 读取 STCMCU 的唯一性ID的例程
#define ID_ADDR_RAM 0xF1 //ID号的存放在RAM区的地址为0F1H#define ID_ADDR_ROM 0x0FF9 //4K程序空间的MCU(如STC15F204EA, STC15F104EA)
unsigned char UID[8];#define RAMID 0#define ROMID 1char *GetMCUID(unsigned char nType);char *GetMCUID(unsigned char nType)  //获取 MCU ID {     unsigned char idata *iptr;     unsigned char code *cptr;     unsigned char i;     unsigned char bb[8];         if (nType == RAMID) 
    {         iptr = ID_ADDR_RAM; //从RAM区读取ID号         for (i=0; i小于7; i++) 
        { //读7个字节
            UID[i] =*iptr++;                   sprintf(bb, "%02x",(int)UID[i]); //Keil C51中,若想得到正确的2字符十六进制数输出,必须使用(int)形式做转换             SendStr(bb);         }     }     else 
    {         cptr = ID_ADDR_ROM; //从程序区读取ID号         for (i=0; i小于7; i++)
        { //读7个字节             UID[i] =*cptr++;              sprintf(bb, "%02X",(int)UID[i]);             SendStr(bb);         }     }     UID[7]=0;    return UID; }

-----------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------

1)前言

STC低档单片机没有硬仿真功能,可以通过串口发送至上位机电脑。在无仿真的环境下,查看程序的执行情况,比如程序执行到哪、变量的值等。串口问题参见通信-RS232、RS485、RS422。

--------------------------------
2)通过STC-ISP查看数据
(1)操作环境
12MHz晶振,USB转RS232串口线连接一个STC下载线,再连接ISP下载器,如下图所示。

(2)电脑接收数据错误
ISP下载程序没有异常,所示说整个连接与电路应该没有问题。但是在单片机发送数据到串口调试类软件时数据不对,仔细查看程序未发现有异常。

可以查看Voltage[]数组的数据

最后定晶振12MHz-->11.0592MHz即可。

波特率计算如下图,也可计算定时器定时初值。

程序下载完成后,自动打开串口查看数据。

--------------------------------
3)通过USB转TTL查看数据

STC12C5608AD(28Pin)单片机通过上述波特率计算,11.0592MHz、TL1=TH1=0xFD,得波特率9600。

但在STC-ISP下载软件中波特率需设置4800才能正常接收数据,如下图。

-----------------------------------------------------------

1)管脚排布

其管脚排布按AT89C51,如下图。

--------------------------------

2)仿真使用方法

详见“STC仿真器使用指南(教程)”,如下所述。

(1)安装Keil版本的仿真驱动

如上图,首先选择“Keil仿真设置”页面,点击“添加MCU型号到Keil中”,在出现的如下的目录选择窗口中,定位到Keil的安装目录(一般可能为“C:\Keil\”),“确定”后出现下图中右边所示的提示信息,表示安装成功。添加头文件的同时也会安装STC的Monitor51仿真驱动STCMON51.DLL,驱动与头文件的的安装目录如上图所示。

-------------------------------- (2)在Keil中创建项目 若第一步的驱动安装成功,则在Keil中新建项目时选择芯片型号时,便会有“STC MCU Database”的选择项,如下图

然后从列表中选择响应的MCU型号,此处我们在此选择“STC15F2K60S2”的型号(实际需使用IAP15F2K61S2或IAP15L2K61S2等),点击“确定”完成选择

添加源代码文件到项目中,如下图:

保存项目,若编译无误,则可以进行下面的项目设置了。

附加说明一点:当创建的是C语言项目,且有将启动文件“STARTUP.A51”添加到项目中时,里面有一个命名为“IDATALEN”的宏定义,它是用来定义IDATA大小的一个宏,默认值是128,即十六进制的80H,同时它也是启动文件中需要初始化为0的IDATA的大小。所以当IDATA定义为80H,那么STARTUP.A51里面的代码则会将IDATA的00-7F的RAM初始化为0;同样若将IDATA定义为0FFH,则会将IDATA的00-FF的RAM初始化为0。虽然STC15F2K60S2系列的单片机的IDATA大小为256字节(00-7F的DATA和80H-FFH的IDATA),但由于STC15F2K60S2在RAM的最后17个字节有写入ID号以及相关的测试参数,若用户在程序中需要使用这一部分数据,则一定不要将IDATALEN定义为256。 -------------------------------- (3)项目设置,选择STC仿真驱动

如上图,首先进入到项目的设置页面,选择“Debug”设置页,第2步选择右侧的硬件仿真“Use …”,第3步,在仿真驱动下拉列表中选择“STC Monitor-51 Driver”项,然后点击“Settings”按钮,进入下面的设置画面,对串口的端口号和波特率进行设置,波特率一般选择115200或者57600。到此设置便完成了。 -------------------------------- (4)创建仿真芯片

准备一颗IAP15F2K61S2或IAP15L2K61S2芯片,并通过下载板连接到电脑的串口,然后如上图,选择正确的芯片型号,然后进入到“Keil仿真设置”页面,在单片机无外加电源的前提下,点击“将所选目标单片机设置为仿真芯片”按钮,当程序下载完成后仿真器便制作完成了,如下图。

注:在未修改程序的前提下,只需创建1次即可,断电仍然有效(重上电后不能运行,在Keil中运行)。由于每次创建仿真芯片时间较长,故修改程序后,先下载/编程测试,若不正常再作仿真。

-------------------------------- (5)开始仿真 将制作完成的仿真芯片通过串口与电脑相连接。 将前面我们所创建的项目编译至没有错误后,按“Ctrl+F5”开始调试。 若硬件连接无误的话,将会进入到类似于下面的调试界面,并在命令输出窗口显示当前的仿真驱动版本号和当前仿真监控代码固件的版本号 断点设置的个数目前最大允许20个(理论上可设置任意个,但是断点设置得过多会影响调试的速度)。

--------------------------------

6)硬件仿真显示支持新增的寄存器SFR

-----------------------------------------------------------

1)Keil软件硬仿真

Keil软件打开STC-ISP烧录的程序,上面的操作无误的情况下,就可以正式硬仿真了。先打断点,再全速仿真。

--------------------------------

2)切换串口位置

注意:仿真不占用串口,只是占用了P3.0、P3.1两个引脚而已。若需仿真时,仍然使用串口1,只需要在串口初始化代码中把串口1切换到P1.6、P1.7引脚(必须使用内部时钟)或P3.6、P3.7引脚即可。

仿真时USB转串口芯片用CH340, 连接到P3.0、P3.1引脚,然后代码设置串口1挪到P1.6、P1.7, 连接PL2303与PC通信。在STC-ISP中可以很容易区分CH340与PL2303串口号,如下图,这样就做到了CH340仿真与PL2303传数据至电脑(比如协议测试)共存。

-----------------------------------------------------------

比如实际项目使用STC12C5608AD(28Pin)。为方便程序移植,将IAP15F2K60S2.h头文件中不同的地方修改成STC12C5608AD.h中的定义。如下图所示,将ADC_RES-->ADC_DATA(ADC转换结果高8位)、ADC_RESL-->ADC_LOW2(ADC转换结果低2位)。

中断优先级不要改,可能会引起不能进定时器中断之现象。

图4.1.1

-----------------------------------------------------------

1)显示Connect to target system lost

图5.1.1

(1)用户不可访问仿真系统区的0DC00-0F3FFH区域的6K代码空间(STC8系列仿真器用户可任意访问用户的64K代码空间)。

(2)用户不能修改仿真监控程序所使用的XDATA区域。

(3)用户不能向P3.0口、P3.1口写数据。

(4)用户不能使用与P3.0、P3.1相关的中断和功能(包括INT4中断、定时器2时钟输出、定时器2外部计数)。

(5)若仿真源代码为汇编程序,则第一条语句必须是长跳转语句,不能使用JMP、SJMP、AJMP或其它语句(STC8系列仿真器的用户代码不受限制)。

(6)对于IAP15F2K60S2来说,一般来说都是操作了串口端即P3.0、P3.1或未创建仿真芯片。

(7)注:不能使用USB转串口线连接RS232再由SP3232EEN等芯片转TTL电平给单片机,也不能通过基于CP2102多功能USB转UART串口模块,其经过的转换步骤应尽可能的少,否则即使能够创建仿真芯片,但连接Keil失败,如图5.1.1所示。只通过1片CH340T,将USB转TTL电平连接单片机,可参看“STC_ISP下载软件问题汇总与解决之”或“单片机3种烧录方式解析之”。

(8)Keil硬仿真单步执行极容易出现连接目标丢失。

咨询宏晶FAE,上述1)、2)、3)、4)必须满足,另外注意干扰。

对于干扰,对方称输入市电经隔离,使用示波器(设备或仪器及使用之之6)示波器和数字电桥)的接地端连接线路板地。

-----------------------------------------------------------------------------------------------------------------

Keil自带的一个很古老的技术Monitor-51,单片机需要预先写入监控程序,占用一个串口。可以实现运行、停止、单步、断点、查看变量等功能。停止是通过PC发数据使单片机进入串口中断程序,从而打断用户程序运行。运行是退出串口ISR,恢复用户程序运行。断点是通过修改用户程序断点位置的指令,跑飞至监控程序运行。单步运行同理。 Keil原版的Monitor-51,用户程序是在外扩RAM里运行的,非常便于修改,但掉电就丢失了。后来一家叫SST的公司,推出的51单片机具有IAP功能,就是程序可以自己改写Flash内容。SST将Monitor-51改造,用户程序也可以放在Flash中,直接一片单片机就可以仿真,不需要专用硬件,但每加一个断点,单步每走一步,都要擦写Flash,所以速度慢一些,对Flash寿命也有影响。 这一时期出现了很多简易的51仿真器,都是基于SST这一方案做的。再后来,STC横空出世,终于一统全宇宙,独霸51单片机。但因为STC单片机内部没有仿真部件,要想仿真,还是采用了监控程序的方案,基本照搬SST的Monitor-51。 现代的单片机一般集成仿真部件,不占用单片机运行资源,例如ARM、STM8、C8051F等。 单片机内部仿真部分通过特定接口与调试主机通讯,例如JTAG、SWD、SWIM等,这种单片机使用的所谓仿真器其实是一个接口协议转换器,例如JLink、STLink等,就是USB-JTAG-SWD接口转换,实际仿真功能是在单片机内部实现。 早期51比较功能完整的仿真器是采用专用仿真芯片(南京伟福、长沙菊阳微,设备见“设备或仪器及使用之”),仿真时用专用仿真芯片替代目标芯片,调试完成后再换回正式芯片,适合DIP封装(SMD封装通过相应的座转接)使用芯片插座的场合,现在已不多见。简单的OTP单片机也是采用这种仿真技术。

在MCS-51单片机中,高端Silicon的C8051F,其次Winbond的1T与4T以及Dallas的1T与4T,STC在国内使用较广泛。

-----------------------------------------------------------------------------------------------------------------

标签: 集成电路tl062cp

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台