前言
? ? ? ?HC89S003F4
是一颗采用高速低功耗
CMOS
工艺设计开发的增强型
8
位单片机,内部有
16K Bytes FLASH 程序存储器,
256 Bytes IRAM
和
256 Bytes XRAM
,最多
18
个双向
I/O
口,
1
个外设功能引脚全 映射模块 PTM
,5 个
16
位定时器
/
计数器,3 组
12
位带死区控制互补
PWM
,1 个
8
位
PWM
,2 个
UART
, 1 个
SPI
,
16
个外部中断,
11+2
路
12
位
ADC
,四种系统工作模式(正常、低频、掉电和空闲)和
16 个中断源。
?
1.延时函数
代码如下(示例):
#define?? ?ALLOCATE_EXTERN
#include "HC89S003F4.h"
sbit KEY = P2^7;
sbit LED = P0^0;
#define N_KEY?? ?0
#define S_KEY?? ?1
#define D_KEY?? ?2
#define L_KEY?? ?10
#define?? ?MOTO_ON()?? ?PWM0DH = 0x01;?? ?PWM0DL = 0xF4;
#define?? ?MOTO_OFF()?? ?PWM0DH = 0x00;?? ?PWM0DL = 0x00;
bit FlagSysClk10ms; ? ?//10ms标记位
bit FlagSysClk500ms; ? ?//500ms标记位
unsigned char KeyValue = 0;
unsigned char CntSysClk10ms = 0;?? ??? ??? ?//时钟10MS记数
unsigned char CntSysClk500ms = 0;?? ??? ??? ?//时钟500MS记数
unsigned int Bat_Adc = 0;?? ??? ??? ??? ??? ??? ??? ?//电池电量
/***************************************************************************************
? *延时函数*
***************************************************************************************/
void Delay_2us(unsigned int fui_i) ? //2us延时
{
?? ?while(fui_i--);?? ?
}
void Delay_ms(unsigned int fui_i) ? //1ms延时
{
?? ?unsigned int fui_j;
?? ?for(;fui_i > 0;fui_i --)
?? ?for(fui_j = 1596;fui_j > 0;fui_j --);
}
2.TIM0时钟配置1ms计时
代码如下(示例):
/*********************************TIM0时钟配置初始化************************************/
void Timer0_init(void)
{
?? ?TCON1 = 0x00;?? ??? ??? ??? ??? ??? ? ?//Tx0定时器时钟为Fosc
?? ?TMOD = 0x00;?? ??? ??? ??? ??? ??? ? ?//16位重装载定时器/计数器
?? ?//Tim0计算时间 ?? ?= (65536 - 0xFACB) * (1 / (Fosc /Timer分频系数)) = 1333 / (16000000 / 12) = 1 ms
?? ?//定时1ms 反推初值 ?? ?= 65536 - ((1/1000) / (1/(Fosc / Timer分频系数)))
?? ?//?? ??? ? ? ?? ?= 65536 - ((1/1000) / (1/(16000000 / 12))) = 65536 - 1333 = 0xFACB
?? ??? ??? ?
?? ?TH0 = 0xFA;
?? ?TL0 = 0xCB;?? ??? ??? ??? ??? ??? ??? ? ?//T0定时时间1ms
?? ?IE |= 0x02;?? ??? ??? ??? ??? ??? ??? ? ?//打开T0中断
?? ?TCON |= 0x10;?? ??? ??? ??? ??? ??? ? ?//使能T0 ? ?
?? ?EA = 1;?? ??? ??? ??? ??? ??? ??? ??? ? ? ?//打开总中断
}
2.PWM0配置2Hz频率,产生50%占空比
/*************************************PWM0初始化****************************************/
void PWM_init(void)
{
P2M1 = P2M1&0xF0|0x08; //P22设置为推挽输出
P1M0 = P1M0&0xF0|0x08; //P10设置为推挽输出
PWM0_MAP = 0x07; //PWM0通道映射P07口
PWM01_MAP = 0x10; //PWM01通道映射P10口
PWM0C = 0x01; //PWM0、PWM01高有效,时钟8分频
//独立模式下,PWM0和PWM01共用一个周期寄存器
//周期计算 = 0x03E8 / (Fosc / PWM分频系数) = 0x03E8 / (16000000 / 8) = 500us / 2kHz
PWM0PH = 0x03;
PWM0PL = 0xE8;
//占空比计算= 0x0155 / (Fosc / PWM分频系数)
// = 0x01F4 / (16000000 / 8) = 500 / 2000000 = 250us 占空比为250/500 = 50%
PWM0DH = 0x01; //PWM0高4位
PWM0DL = 0xF4; //PWM0低8位
PWM0DTH = 0x01; //PWM01高4位
PWM0DTL = 0xF4; //PWM01低8位
PWM0EN = 0x0F; //使能PWM0,工作于独立模式
}
3.按键扫描状态
unsigned char key_driver(void)
{
static unsigned char key_state = 0; // 按键状态变量
static unsigned int key_time = 0; // 按键计时变量
unsigned char key_return;
key_return = N_KEY; // 清除 返回按键值
switch (key_state)
{
case 0: // 按键状态0按键按下
if (!KEY) key_state = 1; // 有按键按下
break;
case 1: // 按键状态1:软件消抖。按键有效的定义:按键持续按下超过设定的消抖时间。
if (!KEY)
{
key_time = 0; // 一次10ms
key_state = 2; // 进入 按键状态2, 继续判定到底是那种有效按键
}
else key_state = 0; // 如果按键时间没有超过,判定为误触,按键无效,返回 按键状态0,继续等待按键
break;
case 2: // 按键状态2:判定按键有效的种类:是单击,还是长按
if(KEY)
{
key_return = S_KEY; // 返回 有效按键值:单击
key_state = 0; // 返回 按键状态0,继续等待按键
}
else
{
key_time++;
if(key_time >= 200) // 如果按键时间超过2s, 则判定为 长按
{
key_return = L_KEY; // 返回 有效键值值:长按
key_state = 3; // 去状态3,等待按键释放
}
}
break;
case 3: // 等待按键释放
if (KEY) key_state = 0;
break;
default:
key_state = 0;
break;
}
return key_return; // 返回 按键值
}
3.main函数
void main() {?? ??? ? ?? ?System_init(); ?? ?Timer0_init(); ?? ?PWM_init(); ? ? //ADC_init(); ?? ?LED = 1; ?? ?while(1) ?? ?{ ?? ??? ?if(FlagSysClk10ms) ?? ??? ?{ ?? ??? ??? ?FlagSysClk10ms = 0; ?? ??? ??? ?KeyValue = key_driver(); ?? ??? ??? ?switch(KeyValue) ?? ??? ??? ?{ ?? ??? ??? ??? ?case S_KEY: ?? ??? ??? ??? ??? ?LED = ~LED; ?? ??? ??? ??? ??? ?MOTO_OFF(); ?? ??? ??? ??? ?break; ?? ??? ??? ??? ? ?? ??? ??? ??? ?case L_KEY: ?? ??? ??? ??? ??? ?LED = 0; ?? ??? ??? ??? ??? ?MOTO_ON(); ?? ??? ??? ??? ?break; ?? ??? ??? ?}?? ??? ??? ? ?? ??? ?} ?? ??? ?if(FlagSysClk500ms) ?? ??? ?{ ?? ??? ??? ?FlagSysClk500ms=0; ?? ??? ??? ?ADCC0 |= 0x40;?? ??? ??? ??? ??? ?//启动ADC转换 ?? ??? ??? ?while(!(ADCC0&0x20));?? ??? ?//等待ADC转换结束 ?? ??? ??? ?ADCC0 &=~ 0x20;?? ??? ??? ??? ??? ?//清除标志位 ?? ??? ??? ?Bat_Adc = ADCR; ?? ??? ??? ?if(Bat_Adc < 2048) ?? ??? ??? ?{ ?? ??? ??? ??? ?LED = 0; ?? ??? ??? ?} ?? ??? ??? ?else?? ?LED = 1; ?? ??? ?} ?? ?} }
该处使用的url网络请求的数据。
|