1

关于投票
零耗时低频宽脉冲软PWM信号控制KeilC51演示程序

零耗时低频宽脉冲软PWM信号控制Keil C51演示程序
hotpower 发表于 11/17/2004 6:08:46 PM 侃单片机 ←返回版面 按此给该网友发送邮件 按此察看该网友的资料 按此把文章加入收藏夹

/*----------------------------------------------------------------
       零耗时低频宽脉冲软PWM信号控制Keil C51演示程序
C51文件PwmDemo.c
HotPower@126.com    作于2004.11.17与大雁塔村队部
在uV3中对PWM信号进行"实时仿真"效果逼真。
-----------------------------------------------------------------*/
#include
//#include
#include

/*------------------------------------------------
        AT89S5X SFR定义(REGX52.h中未定义)
--------------------------------------------------*/
sfr   AUXR    = 0x8e;
sfr   WDTRST  = 0xa6;
sfr16 TIMEER2 = 0xcc;
sfr16 RCAP2   = 0xca;

/*-----------------------------------------------
        PWM管脚定义
------------------------------------------------*/
sbit  PWM     = P1^0;//可以为任意IO管脚

typedef struct Systemstruct{//系统数据结构
  unsigned int PwmCount;//700~2300uS
  unsigned int RamTest;//内部ram自检变量
/*--------------------------------------------------------------------
注意将STARTUP.A51中的IDATALEN改写为0,RamTest才能完成MCU掉电自检。
IDATALEN        EQU     00H     ; the length of IDATA memory in bytes.
---------------------------------------------------------------------*/
}SystemData;//系统数据结构(此时只是定义了一个新的数据类型SystemData)

//全局变量定义(全局结构)
SystemData SystemBuffers;//申请系统数据结构缓冲区

#define T2_20mS -20000 //MCU主频12MHz,12分频,T2_20mS=20MS

/*----------------------------------------------------------------------
        系统函数
-----------------------------------------------------------------------*/
void MainInit(void);//系统初始化
void ClrWdt(void);//喂狗
void SystemInit(void);//系统初始化
void SystemSetup(void);//系统设置
void SystemIoInit(void);//系统接口初始化
void UserSetup(void);//用户运行环境设置
void TimeInit(void);//定时器定时参数初始化


/*-----------------------------------------
         主程序初始化
-------------------------------------------*/
void MainInit(void)//系统初始化
{
  SystemIoInit();//系统接口初始化
  ClrWdt();//清除看门狗计数器
  if (SystemBuffers.RamTest != 0x55aa) {//内存测试
    SystemInit();//系统上电初始化
  }
  SystemSetup();//系统运行环境设置
  UserSetup();//用户运行环境设置
}

void SystemInit(void)//系统初始化
{
  SystemBuffers.RamTest = 0x55aa;//内存初始化
}

void SystemSetup(void)//系统设置
{
  AUXR = 0x01;//关闭EMI
  TimeInit();//定时器定时参数初始化
  IP = 0x20;//中断优先级ET2
}

void UserSetup(void)//用户运行环境设置
{
/*--------------------------------------------
  在此加入用户运行环境设置代码
----------------------------------------------*/
}

void SystemIoInit(void)
{
  IE = 0x00;//关闭中断
  P0 = 0xff;//P0口初始化
  P1 = 0xfe;//P1口初始化,PWM=0
  P2 = 0xff;//P2口初始化
  P3 = 0xff;//P3口初始化
}

void TimeInit()
{
/*----------------------------------
      定时器0定时参数设置
----------------------------------*/
  TL0 = 0;
  TH0 = 0;
//  TR0 = 1;//启动定时器0
/*----------------------------------
      定时器1定时参数设置
----------------------------------*/
  TL1 = 0xfd;
  TH1 = 0xfd;
  PCON = 0x00;//SMOD_=0,GF0_=0;//清除疯狗标志
//  TR1 = 1;//启动定时器1
/*----------------------------------
      定时器2定时参数设置
----------------------------------*/
  TIMEER2 = T2_20mS;//上电20mS后PWM开始工作
  PWM = 0;//上电后无PWM信号
  SystemBuffers.PwmCount = 700;//首次PWM脉宽为700uS
  RCAP2   = 0 - SystemBuffers.PwmCount;//首次PWM脉宽为700uS
  TR2     = 1;//启动定时器2(上电后20mS内PWM信号为低电平)
/*----------------------------------
      定时器参数设置
----------------------------------*/
  TMOD    = 0x22;//定时方式(8位自动装载)
}




/*---------------------------------------------------------------------
         外部INT0中断服务程序(PWM+10uS)
----------------------------------------------------------------------*/
void int0proc() interrupt IE0_VECTOR using 2
{
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
  if (SystemBuffers.PwmCount <= 2290) //PWM高电平脉宽上界-10
    SystemBuffers.PwmCount += 10;//递增未越界
  else
    SystemBuffers.PwmCount = 700;//递增越界翻到下界
}

/*---------------------------------------------------------------------
         定时器T0中断服务程序
----------------------------------------------------------------------*/
void t0proc() interrupt TF0_VECTOR using 2
{
  if (PCON & GF0_) {//中断是从主循环内跳入的才能喂狗
    ClrWdt();//清除看门狗计数器
    PCON &= ~GF0_;//清除疯狗标志
  }
}

/*---------------------------------------------------------------------
         外部INT1中断服务程序(PWM-10uS)
----------------------------------------------------------------------*/
void int1proc() interrupt IE1_VECTOR using 2
{
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
  if (SystemBuffers.PwmCount > 700) //PWM高电平脉宽下界
    SystemBuffers.PwmCount -= 10;//递减未越界
  else
    SystemBuffers.PwmCount = 2300;//递减越界翻到上界
}


/*------------------------------------
         定时器T1中断服务程序
------------------------------------*/

void t1proc() interrupt TF1_VECTOR using 2
{
/*--------------------------------------------
  在此加入用户代码(与串口复用T1)
----------------------------------------------*/
}

/*------------------------------------
         串口SIO中断服务程序
------------------------------------*/

void sioproc() interrupt SIO_VECTOR using 2
{
  if (RI) {//接收中断
    RI = 0;
/*--------------------------------------------
  在此加入用户串口接收代码
----------------------------------------------*/
  }
  if (TI) {//发送中断
    TI = 0;
/*--------------------------------------------
  在此加入用户串口发送代码
----------------------------------------------*/
  }
}

/*-----------------------------------------------------------------------------
         定时器T2中断服务程序(20mS)
零耗时低频宽脉冲软PWM信号控制演示程序

软件工作环境及要求:
MCU主频12MHz,软PWM控制IO模拟。PWM脉宽调节10uS
PWM频率20mS=50Hz, PWM高电平脉宽700uS~2300uS,PWM低电平脉宽19300uS~17700uS

"零耗时"并非不耗时。只是没用软件空等待等恼人的函数。
其主要原理是利用低频宽脉冲软PWM信号的“低速”而T2的16位定时器自动装载功能。
T2在每个PWM周期内中断两次。即PWM高电平和PWM低电平各中断1次。
合理应用RCAP2的预装载功能并进行简单的减法运算而轻松完成任务的要求。

本演示程序只需经过简单的修改,即可实现变PWM频率等功能。
为演示方便未用宏定义,否则会更通用。但必须在“低频宽脉冲”的相对条件下。

本文纯属虚构,若有雷同请原谅!
------------------------------------------------------------------------------*/

void t2proc() interrupt TF2_VECTOR using 1
{
static unsigned int PwmCount;//系统内部PWM高电平PwmCount(用户无法访问)
/*-----------------------------------------------------------------------------
  PWM软件IO模拟,任务中未加关PWM控制,可以再加限定/PWM电平信号翻转标志。
  即:SystemBuffers.PwmCount=0为关闭PWM电平信号输出(PWM=0)
  注意SystemBuffers.PwmCount不能过小.
  本软PWM控制模块与Windows的原则相同
  --不主张用户直接开展PWM管脚,而是控制SystemBuffers.PwmCount变量。
例:
-------------------------------------------------------------------------------
  if (SystemBuffers.PwmCount == 0) {//关断PWM信号。(不主张用户直接开展PWM管脚)
    PWM = 0;//关闭PWM电平信号输出,并强迫执行RCAP2 = 0 - PwmCount;RCAP2=0(最宽)
    PwmCount = 0;//PWM高电平脉宽为0,PWM低电平脉宽为T2的最大定时时间。
  }
  else
------------------------------------------------------------------------------*/
  PWM = ~PWM;//PWM电平信号翻转

  TF2 = 0;//清除标志
  if (PWM) {//在PWM高电平时至少有700uS的预算时间
/*---------------------------------------------------------------------
  用户只能改写全局变量SystemBuffers.PwmCount,不能改写静态变量PwmCount
----------------------------------------------------------------------*/
    PwmCount = SystemBuffers.PwmCount;//只在PWM上升沿处取用户PWM高电平PwmCount
/*------------------------------------------------------------------------------
   此时RCAP2早已将PWM高电平PwmCount装入到TIMEER2中
   故此时应该计算PWM低电平20mS-PwmCount到RCAP2中
------------------------------------------------------------------------------*/
//    RCAP2 = 0 - (20000 - PwmCount);//注意定时器是+1器
    RCAP2 = PwmCount - 20000;//(优化计算)注意定时器是+1器(RCAP2首次为-19300)
  }
  else {//在PWM低电平时至少有17700uS的预算时间
/*------------------------------------------------------------------------------
   此时RCAP2早已将PWM低电平20mS-PwmCount装入到TIMEER2中
   故此时应该计算PWM高电平PwmCount到RCAP2中
-------------------------------------------------------------------------------*/
    RCAP2 = 0 - PwmCount;//注意定时器是+1器(RCAP2首次为-700)
  }
/*------------------------------------------------------------------------------
   PWM高电平RCAP2定时时间 + PWM低电平RCAP2定时时间 = PWM周期20mS
-------------------------------------------------------------------------------*/
}


void ClrWdt(void)//喂狗
{
  WDTRST = 0x1e;//89s52内狗
  WDTRST = 0xe1;//89s52内狗
}


void main(void)
{
  MainInit();//系统初始化
  while (1) {//主循环
    IE   |= 0xbf;//保证全部中断可靠
    TCON |= 0x55;//保证定时器打开,外部中断为边沿触发.
    PCON |= GF0_ | IDL_;//喂疯狗(GF0_=1)并进入空闲状态(IDL_=1)
    _nop_();
    _nop_();
  }
}

系统分类: 单片机
用户分类: 51演示程序
标签: 无标签
来源: 原创
发表评论 阅读全文(725) | 回复(0)

1

关于投票
keilC51汉字0xfd出错测试程序

汉字0xfd出错测试程序
hotpower 发表于 2004-11-14 21:59 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖举报该贴

/*-----------------------------------------------------
    汉字0xfd出错测试程序(keil C51 V7.50测试)

HotPower@126.com         2004。11。14
------------------------------------------------------*/

#include
#include

code unsigned char strs[] = "汉字0xfd出错测试程序";
code unsigned char *str[16] = {
   {"\x00\xfd\x01\xfd\x02\xfd\x03\xfd\x04\xfd\x05\xfd\x06\xfd\x07\xfd\x08\xfd\x09\xfd\x0a\xfd\x0b\xfd\x0c\xfd\x0d\xfd\x0e\xfd\x0f\xfd"},
   {"\x10\xfd\x11\xfd\x12\xfd\x13\xfd\x14\xfd\x15\xfd\x16\xfd\x17\xfd\x18\xfd\x19\xfd\x1a\xfd\x1b\xfd\x1c\xfd\x1d\xfd\x1e\xfd\x1f\xfd"},
   {"\x20\xfd\x21\xfd\x22\xfd\x23\xfd\x24\xfd\x25\xfd\x26\xfd\x27\xfd\x28\xfd\x29\xfd\x2a\xfd\x2b\xfd\x2c\xfd\x2d\xfd\x2e\xfd\x2f\xfd"},
   {"\x30\xfd\x31\xfd\x32\xfd\x33\xfd\x34\xfd\x35\xfd\x36\xfd\x37\xfd\x38\xfd\x39\xfd\x3a\xfd\x3b\xfd\x3c\xfd\x3d\xfd\x3e\xfd\x3f\xfd"},
   {"\x40\xfd\x41\xfd\x42\xfd\x43\xfd\x44\xfd\x45\xfd\x46\xfd\x47\xfd\x48\xfd\x49\xfd\x4a\xfd\x4b\xfd\x4c\xfd\x4d\xfd\x4e\xfd\x4f\xfd"},
   {"\x50\xfd\x51\xfd\x52\xfd\x53\xfd\x54\xfd\x55\xfd\x56\xfd\x57\xfd\x58\xfd\x59\xfd\x5a\xfd\x5b\xfd\x5c\xfd\x5d\xfd\x5e\xfd\x5f\xfd"},
   {"\x60\xfd\x61\xfd\x62\xfd\x63\xfd\x64\xfd\x65\xfd\x66\xfd\x67\xfd\x68\xfd\x69\xfd\x6a\xfd\x6b\xfd\x6c\xfd\x6d\xfd\x6e\xfd\x6f\xfd"},
   {"\x70\xfd\x71\xfd\x72\xfd\x73\xfd\x74\xfd\x75\xfd\x76\xfd\x77\xfd\x78\xfd\x79\xfd\x7a\xfd\x7b\xfd\x7c\xfd\x7d\xfd\x7e\xfd\x7f\xfd"},
   {"\x80\xfd\x81\xfd\x82\xfd\x83\xfd\x84\xfd\x85\xfd\x86\xfd\x87\xfd\x88\xfd\x89\xfd\x8a\xfd\x8b\xfd\x8c\xfd\x8d\xfd\x8e\xfd\x8f\xfd"},
   {"\x90\xfd\x91\xfd\x92\xfd\x93\xfd\x94\xfd\x95\xfd\x96\xfd\x97\xfd\x98\xfd\x99\xfd\x9a\xfd\x9b\xfd\x9c\xfd\x9d\xfd\x9e\xfd\x9f\xfd"},
   {"\xa0\xfd\xa1\xfd\xa2\xfd\xa3\xfd\xa4\xfd\xa5\xfd\xa6\xfd\xa7\xfd\xa8\xfd\xa9\xfd\xaa\xfd\xab\xfd\xac\xfd\xad\xfd\xae\xfd\xaf\xfd"},
   {"褒饼昌除待谍洱俘庚过糊积箭烬君魁"},
   {"例笼慢谬凝琵讫驱三升数她听妄锡淆"},
   {"旋妖引育札正铸\xd7\xfd\xd8\xfd\xd9\xfd\xda\xfd\xdb\xfd\xdc\xfd\xdd\xfd\xde\xfd\xdf\xfd"},
   {"\xe0\xfd\xe1\xfd\xe2\xfd\xe3\xfd\xe4\xfd\xe5\xfd\xe6\xfd\xe7\xfd\xe8\xfd\xe9\xfd\xea\xfd\xeb\xfd\xec\xfd\xed\xfd\xee\xfd\xef\xfd"},
   {"\xf0\xfd\xf1\xfd\xf2\xfd\xf3\xfd\xf4\xfd\xf5\xfd\xf6\xfd\xf7\xfd\xf8\xfd\xf9\xfd\xfa\xfd\xfb\xfd\xfc\xfd\xfd\xfd\xfe\xfd\xff\xfd"}
};
void main(void)
{
unsigned char i, j;
unsigned char *s, err = 0;
  SCON = 0x52;
  TMOD = 0x20;
  TH1  = 0xf3;
  TR1  = 1;
  if ((strs[0] == 0xba) && (strs[1] == 0xba)) {//"汉"
    printf("\n'汉'通过!!!");
  }
  else printf("\n'汉'出错!!!");
  if ((strs[2] == 0xd7) && (strs[3] == 0xd6)) {//"字"
    printf("\n'字'通过!!!");
  }
  else printf("\n'字'出错!!!");
  for (i = 0; i < 16; i ++) {
    s = str[i];
    for (j = 0; j < 16; j ++) {
      if ((*s != (i * 16 + j)) || (*(s + 1) != 0xfd))
        err ++;//V7.50有48个FD汉字出错!!!
      s += 2;
    }
  }
  if (err) printf("\n0xFD汉字出错!!!");//V7.50有48个FD汉字出错!!!
  else {
    for (i = 0; i < 16; i ++) {
      printf("\n");
      s = str[i];
      for (j = 0; j < 16; j ++) {
        printf("%c%c", *s, *(s + 1));      
        s += 2;
      }
    }
  }
  while(1);
}

系统分类: 单片机
用户分类: 51演示程序
标签: 无标签
来源: 原创
发表评论 阅读全文(637) | 回复(0)

1

关于投票
DS1302源程序
DS1302源程序
hotpower 发表于 2004-9-13 13:10 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖举报该贴

//打开DS1302
void TimeSpiOpen(void)
{
  TIMECLK = 0;
  TIMERST = 0;//禁止DS1302
  TIMEIO  = 1;//释放数据总线
  TIMERST = 1;//使能DS1302
}

//关闭DS1302
void TimeSpiClose(void)
{
  TIMERST = 0;//禁止DS1302
  TIMEIO  = 1;//释放数据总线
  TIMECLK = 1;
}
//读写DS1302
unsigned char TimeSpiReadWrite(unsigned char val)
{
unsigned char i;
  ACC = val;//取8位数据
  for (i = 8;i > 0; i--)
  {
    TIMECLK = 0;//时钟下降沿输入数据(DS1302读)
    _nop_();//延时
    CY = TIMEIO;//接收串行数据到CY
    _rrca_();//右移一位数据到CY(先存后取)
    TIMEIO = CY;//发送串行数据
    TIMECLK = 1;//时钟上升沿打入数据(DS1302写)
    TIMEIO  = 1;//释放数据总线
  }
  val = ACC;
  return val;
}

//读DS1302字节
unsigned char TimeByteRead(unsigned char address)
{
  TimeSpiOpen();//打开DS1302
  TimeSpiReadWrite(address);//写入DS1302命令
  address = TimeSpiReadWrite(0xff);//读入DS1302数据
  TimeSpiClose();//关闭DS1302
  return address;//返回数据
}

//读DS1302RAM字节
unsigned char TimeRamByteRead(unsigned char address)
{
  TimeSpiOpen();//打开DS1302
  TimeSpiReadWrite((address << 1) | 0xc1);//写入DS1302命令
  address = TimeSpiReadWrite(0xff);//读入DS1302数据
  TimeSpiClose();//关闭DS1302
  return address;//返回数据
}


//写DS1302字节
void TimeByteWrite(unsigned char address, unsigned char val)
{
  TimeSpiOpen();//打开DS1302
  TimeSpiReadWrite(address);//写地址
  TimeSpiReadWrite(val);//写数据
  TimeSpiClose();//关闭DS1302
}

//写DS1302字节
void TimeRamByteWrite(unsigned char address, unsigned char val)
{
  TimeSpiOpen();//打开DS1302
  TimeSpiReadWrite((address << 1) | 0xc0);//写地址
  TimeSpiReadWrite(val);//写数据
  TimeSpiClose();//关闭DS1302
}

//使能DS1302写保护
void TimeWriteEnable(void)
{
  TimeByteWrite(timewriteregall, timewriteseg);//使能DS1302写保护
}

//开放DS1302写保护
void TimeWrieDisbale(void)
{
  TimeByteWrite(timewriteregall, 0);//开放DS1302写保护
}

//DS1302工作开始
void TimeWorkStart(void)
{
unsigned char val;
  val = TimeByteRead(timereadseg);//读秒数据
  val &= 0x7f;//打开晶振
  TimeWrieDisbale();//开放DS1302写保护
  TimeByteWrite(timewriteseg, val);//打开晶振
  TimeByteWrite(tricklewrite, 0xa5);//打开充电二极管
  TimeWriteEnable();//使能DS1302写保护
}

http: