合泰HT66F018编程介绍

HT-IDE3000的使用

详细的HT-IDE3000使用手册可以在HT-IDE3000中直接打开:帮助->Holtek HT-IDE3000使用手册。

模块解析

HT66F018的数据手册可在Holtek官网自行下载,也可点击此处下载

1. 时钟配置

工程创建好之后,通过:工具->配置选项,可对系统的工作电压、时钟源、频率等进行修改。
本例程的配置:

  • SysVolt = 5.0V;
  • Vdd = 5.0V;
  • OSC = internal RC + IO1/IO2; (使用内部RC)
  • HIRC = 8MHz;
  • fsub clock = LIRC;

SMOD寄存器在上电复位后的初始值为0000 0011,本程序不再对其修改,故最终的时钟是使用内部高速时钟:8MHz。该寄存器的详细信息在datasheet中工作模式和系统时钟一节。
SMOD寄存器

2. 端口配置

端口配置不外乎输入/输出模式的选择,以及上拉电阻的配置。合泰的头文件HT66F018.h中,所有寄存器都是以“_”开头,使用小写字母

  • 每一个输入/ 输出口都具有各自的控制寄存器,即PAC~PCC,用来控制输入/输出状态:0–输出,1–输入;上电复位后默认为输入模式;
  • 上拉电阻可通过寄存器PAPU~PCPU 来设置,它用一个PMOS 晶体管来实现上拉电阻功能:0–不上拉,1–上拉
  • PA 口唤醒:单片机进入休眠或空闲模式后,。唤醒单片机有很多种方法,其中之一就是使 PA 口的其中一个引脚从高电平转为低电平。PA 口的每个引脚可以通过设置PAWU 寄存器来单独选择是否具有唤醒功能:0–不使能,1使能
    示例代码:
    _acerl = 0; //disable all AD
	
	//PA口配置
    _pac = 0x68;    //0110 1000
    _papu = 0x08;   //0000 1000
    _pa = 0x04;     //0000 0100
    _pawu = 0x0;    //禁止PA唤醒功能

    //PB口配置
    _pbc = 0x07;    //0000 0111
    _pbpu = 0x00;
    _pb = 0x00;
	
    //PA0口拉高
    _pa0 = 1;

    //判断PA3口的端口电平状态
    if (0 == _pa3)

A/D 转换控制寄存器的上电初始状态默认PA4-PA7, PB0-PB3 为模拟信号输入引脚,但A/D 转换功能并没自动开启。因些需注意若要将PA4-PA7, PB0-PB3用作数字信号输入引脚,或其它功能,需在程序中修改A/D 转换控制寄存器值以关闭A/D 功能。另外需注意A/D 通道使能,内部上拉电阻将自动断开。

3. 定时器

HT66F018包含3 个TM, 分别命名为TM0,TM1 和TM2。每个TM 可被划分为一个特定的类型,即简易型TM(CTM),标准型TM(STM) 或周期型TM(PTM)。
下面提供使用TM0定时1ms,TM1定时200us的配置代码:

    _cpc = 0x08;    //关比较器
    _tmpc = 0;  //禁止TMn输入/输出引脚

    _tm0c0 = 0x00; //TM0时钟为系统时钟4分频(Fsys=8M),则TM0时钟为2M,并关闭定时器
    _tm0c1 = 0xC1;  //定时/计数器模式模式,比较器A匹配(即16位比较)
    _tm0al = 0xD0;  //定时器T0赋初值,定时1ms
    _tm0ah = 0x07;

    _tm1c0 = 0x00;  //TM1时钟为系统时钟4分频(Fsys=8M),则TM1时钟为2M,并关闭定时器
    _tm1c1 = 0xC1;  //1100 0001 定时器模式,比较器A匹配
    _tm1al = 0x90;
    _tm1ah = 0x01;  //定时器T1赋初值,定时200us

简易型TM 核心是一个由用户选择的内部或外部时钟源驱动的16 位向上计数器,它还包括两个内部比较器即比较器A 和比较器P。这两个比较器将计数器的值与CCRP 和CCRA 寄存器中的值进行比较。CCRP 是8 位的,与计数器的高8 位比较;而CCRA 是16 位的,与计数器的所有位比较。

定时器的功能比较复杂,其他模式的配置请自行参见datasheet中的介绍。

4. 中断

4.1 中断使能

HT66F018提供多个外部中断和内部中断功能,外部中断由INT0~INT1 引脚动作产生,而内部中断由各种内部功能,如定时器模块、比较器、时基、LVD、EEPROM 和A/D 转换器等产生。
下面提供的代码接上一节定期器的内容,使能定时器T0和T1的中断,同时打开外部中断0:

    _integ = 0x03;      //外部INT0中断双沿控制
    _intc0 = 0x08;      //使能外部中断0,使能多功能中断0(其中包括TM0定时)
    _intc1 = 0x01;      //使能多功能中断1(即使能TM1中断)

    _intc2 = 0x00;      //禁止其它中断

    _mfi0 = 0x02;       //TM0比较匹配A中断使能
    _mfi1 = 0x02;       //TM1比较匹配A中断使能
    _mfi2 = 0x00;       //禁止其它中断

    _emi = 1;   //开总中断
    _t0on = 1;  //启动定时器0
    _t1on = 1;  //启动定时器1
    _int0e = 1; //使能外部中断0

通过禁止相关中断使能位,可以屏蔽中断请求,然而,一旦中断请求标志位被设定,它们会被保留在中断控制寄存器内,直到相应的中断服务子程序执行或请求标志位被软件指令清除。
多功能中断中所含中断相应程序执行时,多功能中断请求标志MF0F-MF2F 可以自动清零,但各自的请求标志需在应用程序中手动清除。

4.2 中断函数编写

如下图展示的是HT66F018的中断结构图,可以在datasheet的Page117中找到,在编写中断函数时,主要需要用到下图中的*Vector(中断向量)*一列。各个中断使能位以及相应的请求标志位,以优先级的次序显示在下图。一些中断源有自己的向量,但是有些中断却共用多功能中断向量。
中断结构

/* timer0 interrupt, 1ms */
void __attribute((interrupt(0x0C))) timer0(void)
{
    _t0af = 0;	//清除T0中断标志位
	
    //user code start
    //...
    //user code end

    /* 一旦中断子程序被响应,系统将自动清除EMI位,所有其它的中断将被屏蔽 */
    _emi = 1;   //手动打开总中断
}
/* timer1 interrupt, 200us */
void __attribute((interrupt(0x10))) timer1(void)
{
    _t1af = 0;
	
    //user code start
    //...
    //user code end

    /* 一旦中断子程序被响应,系统将自动清除EMI位,所有其它的中断将被屏蔽 */
    _emi = 1;   //手动打开总中断
}
/* int0 *、
void __attribute((interrupt(0x04))) Int0(void)
{
    //不需要清除中断标志位
	
    _emi = 1;   //手动打开总中断
}

一旦中断子程序被响应,系统将自动清除EMI位,所有其它的中断将被屏蔽,这个方式可以防止任何进一步的中断嵌套。其它中断请求可能发生在此期间,虽然中断不会立即响应,但是中断请求标志位会被记录。

5. ADC

HT66F018包含一个多通道的A/D转换器,它们可以直接接入外部模拟信号(来自传感器或其它控制信号)并直接将这些信号转换成12位的数字量。
转换流程如下:ADCR0 寄存器中的START 位,用于打开和复位A/D 转换器。当单片机设定此位从逻辑低到逻辑高,然后再到逻辑低,就会开始一个模数转换周期。当START 位从逻辑低到逻辑高,但不再回到逻辑低时,ADCR0 寄存器中的EOCB 位置“1”,复位模数转换器。START 位用于控制内部模数换转器的开启动作。ADCR0 寄存器中的EOCB 位用于表明模数转换过程的完成。在转换周期结束后,EOCB 位会被单片机自动地置为“0”。
代码描述:

void adc_init()
{
    _adcr0 = 0x00;
    _adrfs = 0; //ADC 数据高字节是ADRH 的bit 3~bit 0,低字节是ADRL 的bit 7~bit 0
    _adcr1 = 0x03;      //设置AD参考为内部ADC电源,确定时钟为系统时钟8分频,即AD时钟周期为1us.
                        //AD转换时间为16个AD时钟周期。
    _acerl = 0x26;      //选择PA6/pb2/pb1为AD输入引脚(AN5/AN2/AN1)
}

/* 根据通道值获取ADC采样值 */
uint16_t GetAdResult(uint8_t adc_chan)
{
    uint16_t result;

    _adcr0 = adc_chan;

    _start = 0;
    _start = 1;
    _start = 0;

    while(_eocb);

	//_adrfs为0,使用下面数据格式拼接处结果
    result = (_adrh << 4) & 0xFF0;
    result = result | ((_adrl >> 4) & 0xF);

    return result;
}

总结

HT66F018的编码总体来说还是比较简单的,只是存在不少的坑,比如中断服务中单片机会自动清除emi,这种情况我还是第一回碰到。最后要说的是,多读几遍datasheet是关键,很多编程的关键点在datasheet中都有说明;中文的datasheet,理解起来也比较快。

  • 11
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值