|||
/*自己编写的STC12C4052AD底层库文件,已上机调试过,希望能给初次用这块单片机的人一些帮助,希望大家支持,谢谢*/
/************************************************************************/
/* Name: STC12C4052AD_LIB.C */
/* Language: C51单片机编程语言 */
/* Platform: */
/* Author: FRANK FONG , huananfang@hotmail.com */
/* Date: 2010-05-21,上海; */
/* Version: */
/* Deion: AD ; PWM ; EEPROM */
/************************************************************************/
#include <STC12C2052AD.H>
#include <string.h>
#include <intrins.h>
#define ENABLE_ISP 0x8A //10001010,打开ISP功能,设置Flash时间
typedef unsigned char INT8U;
typedef unsigned int INT16U;
//关闭ISP 功能, 清相关的特殊功能寄存器
void ISP_Disable()
{
ISP_CONTR = 0; //关闭ISP 功能
ISP_CMD = 0; //清命令寄存器,使命令寄存器无命令,此句可不用
ISP_TRIG = 0; //清命令触发寄存器,使命令触发寄存器无触发
ISP_ADDRH = 0;
ISP_ADDRL = 0;
}
//eeprom 寻址共用体
union union_temp16
{
INT16U un_temp16;
INT8U un_temp8[2];
}my_unTemp16;
//延时函数
void delay(INT8U delay_time)
{
INT16U n;
while(delay_time--)
{
n = 6000;
while(--n);
}
}
//adc初始化 ( 已放在AD转换 里面)
//void adc_power_on()
//{
// ADC_CONTR = 0xC0; //11000000,开AD电源,SPEED 420时钟周期转换一次,缺省选通道P1.0
// delay(1); //开A/D转换电源后要加延时
//}
//adc_power_off
//void adc_power_off()
//{
// ADC_CONTR &= 0x7F;
// delay(1);
//}
//AD转换
INT8U adc_result (INT8U channel)
{
INT8U DATA_adccontr = 0xC0;
channel &= 0x07; //0000,0111 清0高5位
DATA_adccontr = 0xC0 + channel; //选AD通道,0-p10,1-p11,2-p12,3-p13,4-p14
ADC_CONTR = DATA_adccontr; //开AD电源,SPEED 420时钟周期转换一次
delay(1); //开A/D转换电源后要加延时
DATA_adccontr=DATA_adccontr&0xef; //与11101111对adc_flag清0
ADC_CONTR=DATA_adccontr;
DATA_adccontr=DATA_adccontr|0x08; //或1000 对ADC_START置位,开始ADC
ADC_CONTR=DATA_adccontr;
delay(1); //延时
while (1) //等待A/D转换结束
{
if (ADC_CONTR & 0x10) //0001,0000 测试A/D转换结束否
{
break;
}
}
ADC_CONTR &= 0xE7; //与1110,0111 清 ADC_FLAG 位, 关闭A/D转换
return ADC_DATA; //返回 A/D 8 位转换结果
}
//读一字节,调用前需打开ISP功能
INT8U Byte_Read(INT16U add)
{
ea=0;
ISP_DATA = 0x00;
ISP_CONTR = ENABLE_ISP; //10001010,打开ISP功能,设置Flash时间
ISP_CMD = 0x01; //IAP/ISP/EEPROM 字节读命令
my_unTemp16.un_temp16 = add;
ISP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
ISP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
ISP_TRIG = 0x46; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
ISP_TRIG = 0xB9; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
ISP_Disable();
return (ISP_DATA);
}
//写字节编程,调用前需打开ISP 功能
void Byte_Program (INT16U add, INT8U ch )
{
ISP_CONTR = ENABLE_ISP; //打开 ISP 功能
ISP_CMD = 0x02; //IAP/ISP/EEPROM 字节编程命令
my_unTemp16.un_temp16 = add;
ISP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
ISP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
ISP_DATA = ch; //要编程的数据先送进ISP_DATA 寄存器
ISP_TRIG = 0x46; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
ISP_TRIG = 0xB9; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
ISP_Disable(); //关闭ISP 功能
}
//擦除扇区
void Sector_Erase(INT16U add)
{
ISP_CONTR = ENABLE_ISP; //打开ISP 功能
ISP_CMD = 0x03; //IAP/ISP/EEPROM 扇区擦除命令
my_unTemp16.un_temp16 = add;
ISP_ADDRH = my_unTemp16.un_temp8[0]; //设置目标单元地址的高8 位地址
ISP_ADDRL = my_unTemp16.un_temp8[1]; //设置目标单元地址的低8 位地址
ISP_TRIG = 0x46; //先送 5Ah,再送A5h 到ISP/IAP 触发寄存器,每次都需如此
ISP_TRIG = 0xB9; //送完A5h 后,ISP/IAP 命令立即被触发起动
_nop_();
ISP_Disable(); //关闭IAP 功能
}
//pwm初始化 ,p3.7 输出PWM
void pca_init()
{
CMOD=0x82; //10000010内部时钟Fosc/2
CCON=0x00; //pca flag clear ,pca is stop
CL=0x00;
CCAPM0=0x42; //01000010 ,set pwm mode,使能 CEX0 脚作脉宽调节PWM输出
PCA_PWM0=0x00; // (EPCnH)在pwm模式下,与CCAPnH组成9位数
// (EPCnL)在pwm模式下,与CCAPnL组成9位数,构成捕获寄存器
tr1=1; //开定时1
ea=1; //开中断
CR=1; //启动PWM
}
// p3.7 /CEX0输出 PWM
void pwm_run(INT8U pulse_with)
{
//CCAP0L=pulse_with;
pca_init();
CCAP0H=pulse_with;
}