[通用8051核FLASH系列] 芯圣HC89S003F4简单测试代码

[复制链接]
2249|10
 楼主| qn7a12 发表于 2022-11-26 16:22 | 显示全部楼层 |阅读模式
本帖最后由 芯圣电子官方QQ 于 2023-7-25 11:05 编辑

前言
       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
  2. #include "HC89S003F4.h"

  3. sbit KEY = P2^7;
  4. sbit LED = P0^0;

  5. #define N_KEY    0
  6. #define S_KEY    1
  7. #define D_KEY    2
  8. #define L_KEY    10

  9. #define    MOTO_ON()    PWM0DH = 0x01;    PWM0DL = 0xF4;
  10. #define    MOTO_OFF()    PWM0DH = 0x00;    PWM0DL = 0x00;

  11. bit FlagSysClk10ms;    //10ms标记位
  12. bit FlagSysClk500ms;    //500ms标记位

  13. unsigned char KeyValue = 0;
  14. unsigned char CntSysClk10ms = 0;            //时钟10MS记数
  15. unsigned char CntSysClk500ms = 0;            //时钟500MS记数

  16. unsigned int Bat_Adc = 0;                            //电池电量

  17. /***************************************************************************************
  18.   *延时函数*
  19. ***************************************************************************************/
  20. void Delay_2us(unsigned int fui_i)   //2us延时
  21. {
  22.     while(fui_i--);   
  23. }

  24. void Delay_ms(unsigned int fui_i)   //1ms延时
  25. {
  26.     unsigned int fui_j;
  27.     for(;fui_i > 0;fui_i --)
  28.     for(fui_j = 1596;fui_j > 0;fui_j --);
  29. }







 楼主| qn7a12 发表于 2022-11-26 19:10 | 显示全部楼层
TIM0时钟配置1ms计时

代码如下(示例):
  1. /*********************************TIM0时钟配置初始化************************************/
  2. void Timer0_init(void)
  3. {

  4.     TCON1 = 0x00;                          //Tx0定时器时钟为Fosc
  5.     TMOD = 0x00;                          //16位重装载定时器/计数器

  6.     //Tim0计算时间     = (65536 - 0xFACB) * (1 / (Fosc /Timer分频系数)) = 1333 / (16000000 / 12) = 1 ms

  7.     //定时1ms 反推初值     = 65536 - ((1/1000) / (1/(Fosc / Timer分频系数)))
  8.     //               = 65536 - ((1/1000) / (1/(16000000 / 12))) = 65536 - 1333 = 0xFACB
  9.             
  10.     TH0 = 0xFA;
  11.     TL0 = 0xCB;                              //T0定时时间1ms
  12.     IE |= 0x02;                              //打开T0中断
  13.     TCON |= 0x10;                          //使能T0   
  14.     EA = 1;                                    //打开总中断
  15. }

 楼主| qn7a12 发表于 2022-11-26 19:13 | 显示全部楼层
PWM0配置2Hz频率,产生50%占空比
  1.         /*************************************PWM0初始化****************************************/
  2. void PWM_init(void)
  3. {
  4.         P2M1 = P2M1&0xF0|0x08;                //P22设置为推挽输出
  5.   P1M0 = P1M0&0xF0|0x08;    //P10设置为推挽输出
  6.        
  7.         PWM0_MAP = 0x07;                                        //PWM0通道映射P07口
  8.         PWM01_MAP = 0x10;                                        //PWM01通道映射P10口
  9.   PWM0C = 0x01;                                                  //PWM0、PWM01高有效,时钟8分频

  10.         //独立模式下,PWM0和PWM01共用一个周期寄存器
  11.         //周期计算         = 0x03E8 / (Fosc / PWM分频系数) = 0x03E8 / (16000000 / 8)        = 500us        / 2kHz               

  12.         PWM0PH = 0x03;
  13.         PWM0PL = 0xE8;

  14.         //占空比计算= 0x0155 / (Fosc / PWM分频系数)
  15.         //                        = 0x01F4 / (16000000 / 8)        = 500 / 2000000  = 250us        占空比为250/500 = 50%               

  16.         PWM0DH = 0x01;                                                //PWM0高4位
  17.         PWM0DL = 0xF4;                                                //PWM0低8位
  18.         PWM0DTH = 0x01;                                                //PWM01高4位
  19.         PWM0DTL = 0xF4;                                                //PWM01低8位
  20.         PWM0EN = 0x0F;                                                //使能PWM0,工作于独立模式
  21. }
 楼主| qn7a12 发表于 2022-11-26 19:14 | 显示全部楼层
按键扫描状态
  1. unsigned char key_driver(void)
  2. {     
  3.     static unsigned char key_state = 0;         // 按键状态变量
  4.     static unsigned int key_time = 0;           // 按键计时变量
  5.     unsigned char key_return;
  6.     key_return = N_KEY;                         // 清除 返回按键值
  7.     switch (key_state)     
  8.     {      
  9.         case 0:      // 按键状态0按键按下
  10.             if (!KEY)  key_state = 1; // 有按键按下      
  11.             break;

  12.         case 1:                       // 按键状态1:软件消抖。按键有效的定义:按键持续按下超过设定的消抖时间。
  13.             if (!KEY)                     
  14.             {
  15.                 key_time = 0;               // 一次10ms
  16.                 key_state = 2;    // 进入 按键状态2, 继续判定到底是那种有效按键
  17.             }         
  18.             else key_state = 0;       // 如果按键时间没有超过,判定为误触,按键无效,返回 按键状态0,继续等待按键
  19.             break;

  20.         case 2:                       // 按键状态2:判定按键有效的种类:是单击,还是长按
  21.             if(KEY)
  22.             {
  23.                  key_return = S_KEY;            // 返回 有效按键值:单击
  24.                  key_state = 0;       // 返回 按键状态0,继续等待按键
  25.             }
  26.             else
  27.             {
  28.                 key_time++;                     
  29.                 if(key_time >= 200)   // 如果按键时间超过2s, 则判定为 长按
  30.                 {
  31.                     key_return = L_KEY;         // 返回 有效键值值:长按
  32.                     key_state = 3;    // 去状态3,等待按键释放
  33.                 }
  34.             }
  35.             break;

  36.       case 3:                         // 等待按键释放
  37.           if (KEY) key_state = 0;      
  38.           break;

  39.         default:
  40.           key_state = 0;
  41.           break;
  42.     }
  43.     return key_return;                          // 返回 按键值
  44. }
 楼主| qn7a12 发表于 2022-11-26 19:16 | 显示全部楼层
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;
        }
    }
}

tpgf 发表于 2022-12-7 14:10 | 显示全部楼层
一般说一个芯片是高速芯片 是说其主频高吗
磨砂 发表于 2022-12-7 14:32 | 显示全部楼层
看代码应该是在主函数中进行的轮询吧
晓伍 发表于 2022-12-7 14:42 | 显示全部楼层
FlagSysClk10ms这个标志位应该是用来判定是否到时的吧 在哪里进行计时的呢
八层楼 发表于 2022-12-7 15:08 | 显示全部楼层
按键扫描状态 函数的调用没有体现出来呀
观海 发表于 2022-12-7 15:27 | 显示全部楼层
既然初始化为pwm模式了 为什么还在主函数里边判断呢
guanjiaer 发表于 2022-12-7 15:51 | 显示全部楼层
感觉楼主主函数的操作和外设模块的初始化不匹配
您需要登录后才可以回帖 登录 | 注册

本版积分规则

40

主题

542

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部