keil 中颖单片机

2017-09-19 12:22:48 qq997758497 阅读数 5207
1、中颖单片机SH88F516简介
SH88F516是一种高速高效率8051兼容单片机。在同样振荡频率下,较之传统的8051芯片它具有运行更快速,性能更优越的特性。SH88F516保留了标准8051芯片的大部分特性,这些特性包括内置256字节RAM和2个16位定时器/计数器, 1个UART和外部中断INT0和INT1。此外,SH88F516还集成外置1024字节RAM,可兼容8052芯片的16位定时器/计数器(Timer2)。该单片机还包括适合于程序和数据的64K字节Flash存储器。SH88F516不仅集成了如EUART,SPI等标准通讯模块,此外还集成了具有内建比较功能的ADC,PWM定时器以及模拟比较器(CMP)等模块。为了达到高可靠性和低功耗,SH88F516内建看门狗定时器,低电压复位功能,低电压检测功能和振荡器失效检测功能。此外SH88F516还提供了2种低功耗省电模式。
2、开发环境搭建
1)安装KEIL C51编译环境,这个很简单。

2)安装中颖单片机的官方头文件,官方直接给的是一个可执行文件Sino_Keil.exe。附上下载地址:

http://www.sinowealth.com/zh/xzzq_body_tool_softip.asp?cat_name=8BIT%20MCU&cat_id=32&flag=cat_tool

选择其中的JET51A_Keil插件


下载好解压出来执行Sino_Keil.exe


一路到如下图的位置


箭头指的是Keil的安装目录,这个根据自己的安装目录做修改。


安装完成Finish。

至此就可以编程了,上个图。


3、程序下载
程序下载官方提供的方式有工具下载和串口下载这两种比较常用的方式。
1)串口下载
串口下载没别的,唯一的好处就是省成本,一个USB转TTL搞定。

首先需要下载串口下载工具软件ISP51_Win_V2.9.exe


当然这个也是需要安装的


后面的就不多说了,安装完软件根据软件里面的提示就可,下载也是需要按下复位程序才开始下载的,其实串口下载还是很好使的。我在项目里面因为没有留串口接口,所以选择的工具下载。
2)工具下载

能用的工具有很多,官方介绍的也有好几种,不多介绍。本次选用的是JET51A仿真器。说是仿真器,用起来贼难用。所以我最后都是把它当作下载工具使用而不是仿真工具在使用。直接记上如何下载把。用的软件是ProWriter


他有对应的库。

先安装应用软件,如下:


继续安装库文件


现在插上JAT51A仿真器,长这样


插上电脑后会识别成一个U盘,打开设备管理器可以看到这个便携设备。


如果没有识别成功,那可能需要安装对应的驱动,也可以参考用户指南


打开刚才安装的下载工具软件(中颖编程器)会识别到工具


然后下载一个代码试试,首先配置下,根据型号选择


控制选项选工具的5V供电,这里要注意外部电源要断掉

然后按如下步骤选择编译好的HEX文件


这以上就是整个过程。

By Urien 2017年9月19日 12:51:00

2020-04-20 22:17:10 lljss1980 阅读数 81

问题:中颖单片机调试不正常,不按顺序走,乱跳。

原因一:

在keil4中尝试新建工程,发现中颖单片机的库找不到了,可能是安装其他库的时候出错了。
在这里插入图片描述
卸载中颖库,双击在这里插入图片描述,先卸载,再重新安装在C:\keil中。安装完之后,会多出框中的文件。
在这里插入图片描述
重新在Keil4中新建工程,发现有库了。
在这里插入图片描述
再打开原来工程,发现可以看到单片机了,也可以正常调试了。

原因二:

发现新建工程时可以发现“Sino Wealth 8051 Devices”,可以重新编译程序,先下载一次,再debug,发现可以调试了。可能是直接debug,没有把程序下载进去导致调试无效。

2019-10-16 18:39:26 qq_40257160 阅读数 358

中颖的文档写的感觉不是太清楚,以下是我个人整理的一些比较坑的地方。

一、烧录

烧录必须得买他家的,一般的jtag不能用,一个三百多块钱呢。其次烧录要么用keil4要么用Prowrite这个官方自带的烧录软件。keil4主要是仿真调试用,官方软件用于生产比较方便。

二、代码选项

这个是在烧录的时候一定要注意的问题。

第一,中颖的时钟选择并不是通过某个寄存器选择的,而是要通过代码选项OP_OSC这个来选,如果不选择等你把程序烧进去之后会发现你的外部晶振甚至没有起振(当时给我搞懵了)。

第二,中颖默认代码选项中开门狗是开的,OP_WDT一定要选择关闭。

 

 

三、bank0和bank1

从数据手册或者f3283的头文件里能看到,一些寄存器背后有备注在“bank1”,一定要注意,如果要对这些寄存器进行设置,一定要像以下配置。

这点真的是坑死我了,如果不切换的话一些寄存器的地址是重叠的,到赋值的时候就会出现莫名其妙的错误。包括P5的所有脚都是在bank1的,配置的时候一定要留意。

四、时钟

手册上并没写的太清楚外部晶振究竟能搞到一个什么范围,一会儿说12M一会儿又16M,最后我打了个电话咨询他们工程师才说外部最多12M,内部可以达到16M。

一般51都是一个机器周期=12个震荡周期,这款是1:1,不过需要注意的一点是CLKCON这个寄存器默认将时钟12分频。

使用的时候一定要记得给它设置成不分频,不然速度太慢了

五、ADC采样和串口中断

当你配置完ADC打开中断和总中断之后,一定要等待至少10us的时间再写下:ADCON|=0X01;

否则ADC模块会出现问题。

串口中断的RI和TI任意一个为1时,都不能触发串口中断。

我用了个芯片将232转485了,每次发送完成后一定要把TI这个标志清零再接收,不然根本收不到数据。

六、RAM

不得不说这个RAM实在是太小了,内部就256字节,外部撑死1k,我用的时候真的要很小心,生怕ram满了导致中断保持现场对的时候不正常。

因为自己用51比较少,所以对于keilc51的关键字不太熟悉,以下的解释各位懂行就忽略,算是我自己的理解和笔记吧。

根据数据手册,内部RAM一共有256个字节,其中低位128直接访问就行了。

啥叫直接访问呢,就是你定义一个"int a=0;"这就是直接访问了。

高位128字节的,从地址上看是和SFR相同的,SFR对应的就是我们的各个寄存器。为了区别这两个不同的区域(本身物理上也是分开的)只要你加一个关键字“idata”就可以保证定义的变量是在内部ram里。

比如"idata int a=0;"这就保证它一定在内部ram里面,至于是在00H-FFH的哪个位置,可以通过.M51文件查看。但是你不加这个idata关键字,变量就只储存在内部ram的00H-7FH里了

接下来是外部ram,这里的文字描述就给我看的有些迷糊了。

说这这么一大堆,到底是啥意思呢。他的意思是说,咱们外部RAM支持传统的用汇编指令访问外部ram,也支持用XPAGE寄存器访问外部RAM,我是没弄明白这个XPAGE寄存器怎么用,因为它写的比较模糊,而且我对51真的不怎么了解。

最后我发现:

实际上你只要加一个关键字"xdata"就可以直接把变量定义在外部ram了,例如"xdata int i=0;"

就这么简单,真的。

至于你想验证我定义完之后是不是能正常给这个变量赋值,很简单,你插上这个东西的仿真器,跑一个最简单的i++;语句,看看在watch窗口这个i有没有增加就是了。

另外关于外部ram的访问,我也查到了一些别的资料。在自带的ABSACC.H文件中有这么一个关键字XBATE,可以实现定位储存。具体的用法呢我就贴个网址,大家看看。

https://blog.csdn.net/shenhuxi_yu/article/details/54344362

2014-06-10 11:19:25 chuangwu2009 阅读数 2811
<pre name="code" class="cpp">/*
	中颖EEPROM,使用比较方便,但有个注意点,就是每次无论你写入
	什么数据或者在哪个地址写数据,都需要将对 对应的块擦除,擦
	除后才能写入成功。
*/
#define	 SSPWriteFlag	  0x5A
#define	 SSPEraseFlag	  0xA5	

//数据区 扇形区1
#define		ADDR_START1				(uint16)0x100 //数据存储区起始地址

#define		ADDR_START2				(uint16)0x200 //数据存储区起始地址
//数据区 扇形区2
#define		Addr1UserHave			(uint16)0x101 //用户地址1
#define		Addr2UserHave			(uint16)0x102 //用户地址2

uint8 Ssp_Flag = 0 ;

//*************************************
// 函数名称:Ssp_Write
// 函数功能:SSP擦除某块的地址
// 入口参数:被写数据的地址 数据
// 出口参数:无
//***************************************
void Ssp_EraseBlock(uint16 addr)
{
	CY=EA;
	EA=0;
	IB_CON1 = 0xE6;
	IB_CON2 = 0x05;
	IB_CON3 = 0x0A;
	IB_CON4 = 0x09;
	if(Ssp_Flag != SSPEraseFlag)
		{
			IB_CON2=0;
			goto Erase_Err;
		}
	XPAGE = (addr>>8) & 0x07;	   
	FLASHCON=1;
	IB_CON5 = 0x06;
	_nop_();
	_nop_();
	_nop_();
Erase_Err:
	Ssp_Flag=0;	
	FLASHCON=0;
	XPAGE=0;
	EA = CY;
}

//**************************************
// 函数名称:Ssp_Write
// 函数功能:SSP向某地址写一字节数据
// 入口参数:被写数据的地址 数据
// 出口参数:无
//***************************************
void Ssp_WriteByte(uint16 addr,uint8 dat)
{
	CY=EA;
	EA=0;
	IB_DATA = dat;
	IB_OFFSET = addr&0xff; //取被编程的低8位地址
	IB_CON1 = 0x6E;
	IB_CON2 = 0x05;
	IB_CON3 = 0x0A;
	IB_CON4 = 0x09;
	if(Ssp_Flag != SSPWriteFlag)
	{
		IB_CON2=0;
		goto Write_Err;
	}
	XPAGE = ((addr>>8) & 7); //被编程的扇形区0-3	   
	FLASHCON=1;	//对类EPROM编程开始
	IB_CON5 = 0x06;
	_nop_();
	_nop_();
	_nop_();
	_nop_();
Write_Err:
	Ssp_Flag=0;
	FLASHCON=0;
	XPAGE=0;
	EA = CY;
}
//*************************************
// 函数名称:Read_Flash
// 函数功能:读数据 向FLASH
// 入口参数:读数据的地址
// 出口参数:无
//***************************************
uint8 Read_FlashByte(uint16 addr)
{
	uint8 temp;
	FLASHCON=1;
	temp=*(uint8 code *)(addr);
   	FLASHCON=0;
	return(temp);
}


//应用实例:
 Ssp_EraseBlock(ADDR_START1);//擦除块1
 Ssp_WriteByte(Addr1UserHave,0x88);//在地址Addr1UserHave中写入0x88
 R_Data = Read_FlashByte(Addr1UserHave);//读地址Addr1UserHave的值