[资源共享] 引脚连错了?没关系重映射一下就好了——Holychip HC89F003评测

[复制链接]
758|6
 楼主 | 2017-10-16 23:46 | 显示全部楼层 |阅读模式
本帖最后由 caijie001 于 2017-10-16 23:56 编辑

大家好,我是杰杰。应刘工的邀请,在这里发一篇我的评测,原文链接:http://www.21ic.com/evm/evaluate/MCU/201710/740865.htm
1  产品简介
HC89F003 是一颗采用高频低功耗 CMOS 工艺设计开发的增强型 8 位单片机,内部有 16K Bytes FLASH 程序存储器,256 Bytes IRAM 和 256 Bytes XRAM,18 个双向 I/O 口,5 个 16 位定时器/计数器,3 组 12 位带死区控制互补 PWM,1 个 8 位 PWM,2 个 UART,1 个 SPI,16 个外部中断,8+2 路 12 位ADC,四种系统工作模式(正常、低频、掉电和空闲)和 16 个中断源。

                              
在单片机上用到很多的中断。在这一款芯片上足够满足绝大部分的产品设计。
Hc89f003具有:
  16个中断源
  4级中断优先级
  16个外部中断

重点来了:一般我们的单片机,比如像51,比较少重映射功能的,比如stm32,他们的重映射功能对应的引脚基本都有固定的引脚。但是,hc89f003不一样了,他绝大部分引脚都可以重映射,比如P00可以作为io口,可以重映射为usart_tx、usart_rx、iic、spi等等等等。也就是说,设计板子的时候不用害怕硬件连接错误,只要连接上了,基本可以实现重映射功能。
Datasheet给出的说明:绝大多数复用端口可以映射到任意 I/O 口,但 PWM 故障检测脚、ADC输入、INT0-15 功能口等除外。
注意的是:多个输出映射到一个端口上时,只能有一个输出有效。端口重映射类似中断一样还有优先级的。
*下面是默认的优先级


比如:

CLKO_MAP 配置为 0x01 选择 P0.1 口作为 CLKO 的输出口,T4_MAP也配置为 0x01,这个时候硬件会按上面的优先级,P0.1 将配置为 CLKO 的输出口,而 T4_MAP 的配置无效。

当所有的端口映射控制寄存器都不等于0x01时,即所有的功能口都不选择P0.1作为输入输出口,此时这个端口的输出就是 P0 端口数据寄存器的第 1 位。

输入可以配置为多个功能从一个 PAD 引脚进入,比如:

T0_MAP 配置为 0x23,则选择 P2.3 作为 T0 的输入口,T5_MAP也配置为 0x23,这样从 P2.3 端口进入的信号同时作用于 T3 和 T5。

将 TXD 和 RXD 都配置到一个端口上时,并且此端口设置为输出,则 TXD 和 RXD 将内部连接起来。
在输入时,无论端口是什么功能,读端口数据寄存器都读芯片引脚上值。

对于重映射功能有疑问的请仔细阅读官方datasheet。http://www.holychip.cn/uploadfiles/release/preview/HC89F003_003P_SPEC_Ver1.03.pdf(毕竟是中国芯圣产的,datasheet阅读起来毫无压力,以前看英文的,让我这种四级都没过的孩子头都大了)



HC89F003  使用注意事项 :(官方datasheet的重要说明,使用芯片时一定要认真看datasheet)
1、 为保证系统的稳定性,必须在 VDD 和 GND 之间接一电容(容值须等于或大于 0.1μF)。(对于这点,一般我们用芯片的时候都会这样子做,加个电容)

2、 为保证系统的上电稳定性,建议客户程序在系统产生 POR 复位后进行一次重读代码选项的软复位操作。官方说明这项已经改进(我觉得还是很OK的可以去官网下载新版的datasheet)

3、 当使用 ADC 模块时,不论参考电压选择的是什么,系统工作电压 VDD 必须高于 2.7V。(参考电压一般为GND,这个vdd一般为3.3v)
4、 外部中断在使用查询方式时,无**常清除中断标志位。可以通过先禁止中断使能位再清除中断标志,在完成清除中断标志位后再使能外部中断来进行正常的外部中断产生查询。使用中断方式时,无该问题。
5、 当用户使用 T3 计数时钟源选择端口输入外部时钟,应使 TR3 和 T3CLKS[1:0]的配置同时进行(即用一条指令完成配置)。(个人感觉比较奇怪,但是还是可以按照他的做的。他说一条指令就一条指令吧。)

介绍了那么多,是时候上点开箱图了。
    国庆回家前接到板子,小的让我出乎意料啊,感谢21ic小喇叭,开心。


顺丰快递超快的有木有。。。。。

打开就这点小东西。。

初次见到51—link,有点小小的惊讶。哈哈哈,怪我见识不够。。。。得好好努力了。
打开看看51link里面是什么东西,一看,吓一跳,原来是stm32f1系列芯片。

我也是很佩服芯圣的。。。。



这个小板子做的还是挺精致的,按键,一些必要的电路都搭载在这一小块上面。
20pin的io口所有已经引出了。板载ch340驱动电路

正面,反面



然后下载回来一堆资料,开干,不就是51内核的芯片吗,不难吧。(这是我刚开始的想法。。。我发现我错了,做智能车的时候,我就说过,当你一开始就轻视了它,你就已经输了一半了。。。不过还好,我还是可以把它搞定的哈哈)

到芯圣电子的官网下载回来一堆资料,慢慢看,装驱动,装hc-link,然后打开例程代码,打开datasheet,慢慢搞。。。


我也是先下载回来的,然后先装hc-51link,这个比较简单,那里也有用户手册。
对其他系统讲解的很详细,我是win7的,比较简单。

我电脑系统是64位(bit)的。





请注意:安装在keil文件夹下。
请注意:安装在keil文件夹下。
请注意:安装在keil文件夹下。
重要的事情说3遍


然后一直next就行了,建议把360啊什么杀毒的软件退出再安装。
然后打开flash技术资料> F003 Library Example V1.01
这是库函数版本的例程,很像stm32。入门玩起来不难。
F003 Register ExampleV1.01>这是寄存器版本的。我没看。

随便打开一个gpio的工程:

我初次一看,哎呀,怎么这么熟悉啊,,,,,哈哈哈
进入系统初始化看一下,核心部分就是选择系统时钟
/**
  * @说明     设定系统时钟OSC频率,即外设时钟(Timer UART SPI等)
  * @参数     OscClock :OSC时钟设定值
  *        CLK_OSC_32MHZ //系统时钟32M
  *        CLK_OSC_16MHZ //系统时钟16M
  *        CLK_OSC_8MHZ  //系统时钟8M
  *        CLK_OSC_4MHZ  //系统时钟4M
  *        CLK_OSC_44KHZ //系统时钟44KHZ
  * @返回值 ErrorStatus :表明OSC配置状态
  *        参考ErrorStatus 枚举类.
  * @注    无
  */
ErrorStatus CLK_OscClockConfig(CLK_OscClock_Typedef OscClock)
{
    u8 OscClkBuf;
    if(OscClock ==CLK_OSC_44KHZ)
    {//使用低频作为系统时钟
       CLKSWR =(CLKSWR&(~CLK_SYS_SEL))|CLK_OSC_44KHZ;  //开低频晶振
       while((CLKSWR&CLK_SYS_STA)!=CLK_RC44KHZ_FLAG);//等待晶振起振
       return SUCCESS;                 
    }
    else
    {//使用高频作为系统时钟
       if((OscClock ==CLK_OSC_32MHZ)&&(CLKDIV < CLK_CLKDIV_RESET_VALUE))return ERROR;//如果最终CPU时钟高于20M,则配置失败
       CLKSWR =(CLKSWR&(~CLK_SYS_SEL))|CLK_RC32MHZ;    //启动内部高频
       while((CLKSWR&CLK_SYS_STA)!=CLK_RC32MHZ_FLAG);       //等待高频晶振起振
       OscClkBuf = CLKDIV;
       CLKDIV = 2;                                      //保证CPU工作在20M以下,
       CLKSWR = OscClock|(CLKSWR&(~CLK_RC32M_DIV));     //设置RC32M分频系数
       CLKDIV = OscClkBuf;                              //恢复CPU分频系数
       return SUCCESS;         
    }   
}

HC89F003 单片机系统时钟有 2 种时钟源可选:内部高频 RC 时钟(32 MHz)和内部低频RC 时钟(44KHz)。其中,内部高频 RC 在-40°C ~+85°C 范围误差不超过 1%。选择后的系统时钟(如果选择的是内部高频 RC,则经 RC32M_DIV[1:0]分频后的时钟)记做 osc_clk,其频率为 F osc ,周期为 T osc ,

主要用于外设模块,osc_clk 可以进行 1-255 之间任意值的分频,分频后的时钟记做 CPU 时钟,其频率为 F cpu ,周期为 T cpu 。
CPU 最高可以运行在 20MHz 频率下,如果所选时钟源频率高于 20MHz,需要对其进行分频,使CPU 时钟频率等于或低于 20MHz。
内部低频 RC(RC44K)输出的时钟记做 wdt_clk,用于看门狗定时器的计数,也可以用于系统时钟;内部高频 RC(RC32M)输出的时钟记做 rc32m_clk,可以进行 1/2/4/8 分频。

系统初始化完成就能对芯片的引脚进行操作了。。。。
然后就是GPIO的初始化函数了,芯圣对我们还是很好的,已经集成库函数了,直接调用就OK。
一句代码的事情:
GPIO_Init(GPIOT0,GPIO_PIN_2,GPIO_MODE_IN_PU); //将P02端口设置为上拉电阻模式




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
 楼主 | 2017-10-16 23:46 | 显示全部楼层
本帖最后由 caijie001 于 2017-10-16 23:54 编辑

库函数的使用方法很简单啊,假如我想让P00设置为推挽输出模式。。。
直接将 GPIO_PIN_2变为GPIO_PIN_0。
GPIO_MODE_IN_PU变为GPIO_MODE_OUT_PP

GPIO_Init(GPIOT0,GPIO_PIN_0,GPIO_MODE_OUT_PP);  //P00设置为推挽输出模式

/**
  * @说明     对一组端口中的一个或多个IO设置模式
  * @参数     GPIOx : 初始化的端口组(x:0-2)
  *        GPIOT0 //端口0组

  *        GPIOT1    //端口1组

  *        GPIOT2    //端口2组

  * @参数     GPIO_PIN :    初始化的端口号
  *        GPIO_PIN_0 //选择端口0
  *        GPIO_PIN_1  //选择端口1
  *        GPIO_PIN_2  //选择端口2
  *        GPIO_PIN_3  //选择端口3
  *        GPIO_PIN_4  //选择端口4
  *        GPIO_PIN_5  //选择端口5
  *        GPIO_PIN_6  //选择端口6
  *        GPIO_PIN_7  //选择端口7
  * @参数     GPIO_Mode : 初始化模式
  *        GPIO_MODE_IN             //数字输入
  *        GPIO_MODE_IN_PD          //带下拉输入
  *        GPIO_MODE_IN_PU          //带上拉输入
  *        GPIO_MODE_IN_AN          //模拟输入

  *        GPIO_MODE_IN_SMT         //数字输入  SMT

  *        GPIO_MODE_IN_PD_SMT      //带下拉输入 SMT
  *        GPIO_MODE_IN_PU_SMT      //带上拉输入 SMT
  *        GPIO_MODE_IN_AN_PU_PD    //模拟输入上下拉同时打开,B版以后芯片支持

  *        GPIO_MODE_OUT_PP     //推挽输出

  *        GPIO_MODE_OUT_OD         //开漏输出

  *        GPIO_MODE_OUT_OD_PU //开漏带上拉输出

  * @返回值 无
  * @注       无
  */

void GPIO_Init(GPIO_TypeDefGPIOx,GPIO_Pin_TypeDef GPIO_PIN,GPIO_Mode_TypeDef GPIO_Mode)

{
    u8  i;

    u8 xdata *gpioset;

    gpioset    =0xFF00 | ((GPIOx - 1)<<3);

    for(i=0;i<8;i++){

       if((GPIOx ==GPIOT1)&&(i>1))break;

       if(GPIO_PIN&0x01){

           *(gpioset+i/2) =  ((*(gpioset+i/2)) & (0xF0 >>((i%2)*0x04))) | (GPIO_Mode << ((i%2)*0x04));

       }
       GPIO_PIN >>= 1;
    }
}
上面是void GPIO_Init(GPIO_TypeDef GPIOx,GPIO_Pin_TypeDefGPIO_PIN,GPIO_Mode_TypeDef GPIO_Mode)的原函数。。
有兴趣的可以跳进去看一下。不看也可以。
打开HC89F_GPIO.H
拉倒最下面。有gpio的函数,可以直接调用。

比如我们需要点亮一个led灯,调用这个函数就可以了:
void GPIO_Write(GPIO_TypeDef GPIOx,u8 Value);    //对一组端口赋值
看板子的原理图:


LED1连在HC89F003的P11脚,那我们点亮他就是让P11脚为低电平就行了。
void main(void)
{
    System_init();                                //系统初始化
    GPIO_Init(GPIOT1,GPIO_PIN_1,GPIO_MODE_OUT_PP);  //P00设置为推挽输出模式
    GPIO_Write(GPIOT1,0xFD);           //设置P11脚为低电平
   
    while(1);
}

然后下载到单片机就行了,下载设置的那里,在HC-51LINK用户手册那里写的很详细。

各种配置都写出来了。虽然说有点麻烦,但是,教程很详细,请耐心看完,并且配置完。芯圣是一个用心做产品的厂家。。。
还有我发现一个很特别的地方,这是以前我玩32/51都没有的,那就是上拉电阻阻值大小是可以选择的,可编程选择,芯圣的产品又一次让我惊讶
/**
  * @说明     设置P02端口上拉电阻阻值
  * @参数     Res_Value : 电阻值
  *        R050K  //上拉电阻50K
  *        R100K  //上拉电阻100K
  *        R150K  //上拉电阻150K
  *        R300K  //上拉电阻300K
  * @返回值 无
  * @注       无
  */
调用这个函数就可以了:
void GPIO_P02ExternalPullConfig(GPIO_PullResValveRes_Value)
{
       P0LPU =(P0LPU&(~GPIO_P02PU))|(Res_Value&GPIO_P02PU);   
}
Ex
void main(void)
{
    System_init();                                //系统初始化
    GPIO_Init(GPIOT0,GPIO_PIN_2,GPIO_MODE_IN_PU); //将P02端口设置为上拉电阻模式
    GPIO_P02ExternalPullConfig(R100K); //将P02端口上拉电阻设置为100K
    while(1);
}
就可以将P02端口上拉电阻设置为100K
然后介绍一下HC89f003的重映射功能:
Datasheet介绍:

让我们看看怎么重映射吧,我尽量简单明了讲一下。
什么是重映射:
一般的单片机上有很多I/O口,也有很多的内置外设如I2C、ADC、ISP、USART等,为了节省引出管脚,这些内置外设基本上是与I/O口共用管脚的,也就是I/O管脚的复用功能。很多复用内置的外设的I/O引脚可以通过重映射功能,从不同的I/O管脚引出,即复用功能的引脚是可通过程序改变的。读到这里相信大家都应该了解了端口重映射的一些概念了。原理上的东西不细说了。大家可以看手册或者网上查,这方面的资料还是很多的。

从芯圣的datasheet我们可以知道,基本上所有的io口,都是可以实现重映射的,那我们看看pwm输出能映射到哪个io口呢,

PWM3_OUTPin_P00             = (u8)0x00,       //PWM3输出端口为P00
    PWM3_OUTPin_P01             =(u8)0x01,       //PWM3输出端口为P01
    PWM3_OUTPin_P02             =(u8)0x02,       //PWM3输出端口为P02
    PWM3_OUTPin_P03          =(u8)0x03,       //PWM3输出端口为P03
    PWM3_OUTPin_P04          =(u8)0x04,       //PWM3输出端口为P04
PWM3_OUTPin_P05          = (u8)0x05,       //PWM3输出端口为P05
PWM3_OUTPin_P06          = (u8)0x06,       //PWM3输出端口为P06
    PWM3_OUTPin_P07             = (u8)0x07,       //PWM3输出端口为P07

PWM3_OUTPin_P10             =(u8)0x10,       //PWM3输出端口为P10

PWM3_OUTPin_P11             =(u8)0x11,       //PWM3输出端口为P11

PWM3_OUTPin_P20              = (u8)0x20,      //PWM3输出端口为P20

PWM3_OUTPin_P21             =(u8)0x21,       //PWM3输出端口为P21

PWM3_OUTPin_P22             =(u8)0x22,       //PWM3输出端口为P22

PWM3_OUTPin_P23             =(u8)0x23,       //PWM3输出端口为P23

PWM3_OUTPin_P24             =(u8)0x24,       //PWM3输出端口为P24

PWM3_OUTPin_P25             =(u8)0x25,       //PWM3输出端口为P25

PWM3_OUTPin_P26             =(u8)0x26,       //PWM3输出端口为P26

PWM3_OUTPin_P27             =(u8)0x27,       //PWM3输出端口为P27

这是从芯圣例程找出来的,我数了一下,一路pwm随时在任何一个io口输出。这就是一个重映射,不管你板子设计怎么接线,只要连接到io口,那么就能通过引脚重映射功能,实现你需要的功能,给设计电路带来方便。

voidmain(void)

{
    System_Init();                                  //系统初始化
    GPIO_Init(GPIOT0,GPIO_PIN_1,GPIO_MODE_OUT_PP);  //P01推挽输出
    PWM3_PinRemapConfig(PWM3_OUTPin_P01);           //PWM3输出映射P01口
    PWM3_OutPutCmd(ENABLE);                         //输出使能

    //周期计算  = 0xff / (Fosc / PWM分频系数)   (Fosc见系统时钟配置的部分)

    PWM3_Init(PWM3_HIGH_VALID,PWMCK_8); //PWM3高有效,时钟为OSC时钟8分频

    PWM3_PeriodConfig(0xff);        //PWM3周期为0xFF

    PWM3_DutyCycleConfig(0x55);                     //PWM3的占空比设置
    PWM3_Cmd(ENABLE);                               //PWM3使能
    while(1);
}

核心函数:PWM3_PinRemapConfig(PWM3_OutPin_TypeDef OutPin);                   //PWM3输出管脚映射
直接调用就可以了。
补充一点:一路pwm重映射只能有一个引脚输出pwm,我们不可能实现所有的io都输出同样的pwm波,那岂不是逆天了嘛!!还有就是重映射也有优先级的,这是要注意 的一点。但是我有一个想法,就是分时复用。这个时间段P00口做usart_tx功能,等发送完,我又可以输出pwm,这样不知道行不行,哈哈我的想法而已。

注:本文章皆为原创,如需转载请说明出处:http://www.21ic.com/evm/evaluate/MCU/201710/740865.htm
补充:资料来源:
1):HC89F003技术资料
(出处: 21ic电子技术论坛)
2):上海芯圣电子股份有限公司
http://www.holychip.cn/kfgj/index_14.aspx?lcid=14






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
| 2017-10-17 09:29 | 显示全部楼层
恩 膜拜大佬 抢个沙发    我家代理芯圣的 需要芯圣的加我
| 2017-10-24 10:06 | 显示全部楼层
不错不错!!!!
| 2018-6-23 13:19 | 显示全部楼层
杰杰啊  我怎么感觉你哪种都会啊
 楼主 | 2018-6-23 16:14 | 显示全部楼层
木木guainv 发表于 2018-6-23 13:19
杰杰啊  我怎么感觉你哪种都会啊

不会啊,,,,,我只会stm32但是其他单片机很容易上手而已,,,,我并不会太多。。。
| 2018-6-28 12:10 | 显示全部楼层
caijie001 发表于 2018-6-23 16:14
不会啊,,,,,我只会stm32但是其他单片机很容易上手而已,,,,我并不会太多。。。 ...

太谦虚了 呵呵呵
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

快速回复 返回顶部 返回列表