STC12多中断使用(PWM ADC 串口)

随着时间的发展技术的成熟,STM32的使用难度和上手难度逐渐亲民化,尤其是hal库的出现以及CubeMX软件的出现,使得32开发难度进一步降低,但是由于众多原因的影响导致其价格不断升高,对于企业或者工厂来说,降低成本是第一位需要考虑的,如何使用一款满足当前生产需求,且功能冗余少,稳定开发方便普及且价格低廉的MCU就成了第一位需要考虑的事情,STC12C5A60S2作为51系列单片机家族中的一员,其具备32路普通I/O输入和输出,8路10位ADC数模转换,2路PWM,以及双串口通讯等,以上寄存器基本上满足处理速度要求不高实时性要求不强的系统工作,而STM32家族中对标STC12系列单片机的F103系列当前价格也是飙升,一块STM32可以购买5块及以上STC12,所以对于这种经典8位MCU的使用在实际的生产生活中仍然十分广泛。

以下程序为使用STC12C5A60S2单片机,采用ADC中断扫描模式,并且初始化定时器0进行PWM输出,用串口输出温度数值:
难点:ADC中断与PWM输出靠定时器0发生并且串口通讯波特率靠定时器1发生,这几个中断在代码编写与调试过程中,发现这几个程序独立应用的代码直接移植过来,并不能正常使用,这几个中断的优先级顺序和初始化顺序会产生相互干扰,因此经过查找相关资料,最终解决了这个问题,下面为详细代码(注释是手打上去的,不知道为啥从keil往这里粘贴会出现问题)

void PWM_init() //PWM初始化函数,初始化占空比为0
{
CMOD=0x02; //0000 0010 空闲时不计数,不产生中断,时钟源fosc/2,因此输出占用率fosc/512
CL=0x00;
CH=0x00;
CCAPM0=0x42; //0100 001,8位PWM
CCAP0L=0x00;
CCAP0H=0x00; //PWM实现方法,因为是8位,CL基础计算器从0xFF递减到0x00,溢出后将CCAPOH的值加载到CCAPOL,若CL递减过程中,若大于CCAPOL,则输出高电平,否则为低电平
CCAPM1=0x42;
CCAP1H=0x00;
CCAP1L=0x00;
CR = 1; //开启PCA计数器
}
void PWM_set(uchar x,uchar y) //占空比设置函数 引脚为P1.3和P1.4
{
CCAP0H=x2.55; /占空比公式D=(256-CCAPnH)/256(8位PWM模式)
CCAP0L=x
2.55; //乘2.55转换为0–100%
CCAP1H=y2.55;
CCAP1L=y
2.55;
}
void Timer0_Init(void)
{
TH0=(65536-TIME)/256; //开定时器0
TL0=(65536-TIME)%256;
EA=1; //开全局中断
ET0=1; //允许定时器0中断
TR0=1;

            IE = 0xa0;

}
void timer0() interrupt 1 //interrupt 1: 定时器0中断用于产生PWM波
{
TH0=(65536-TIME)/256; //高八位,(需要表示Xms的定时,计数器由65536-X数到65536,由于16位,只能分高低位)
TL0=(65536-TIME)%256; /低八位
num++;
if(num==500)
{
flagTime ++;
num = 0;
}
Init_ADC();
}
/------------------------------------------------
串口初始化
------------------------------------------------
/
void Init_UART (void)
{
SCON = 0x50; //8位数据,可变波特率
TMOD |= 0x20; //设定定时器1为16位自动重装方式
TL1 = 0xC0; //设定定时器高8位初值
TH1 = 0xFA; //设定定时器低8位初值
TR1 = 1; //启动定时器
EA = 1;
}
/------------------------------------------------
发送一个字节
------------------------------------------------
/
void SendByte(unsigned char dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}
/------------------------------------------------
发送一个字符串
------------------------------------------------
/
void SendStr(unsigned char *s)
{
while(*s!=‘\0’)// \0表示字符串结束标志
/通过检测是否是字符串末尾
{
SendByte(*s);
s++;
}

}
/----------------------------
ADC interrupt service routine
----------------------------
/
void adc_isr() interrupt 5 using 1
{
//V_5REF=V_1REF*256/da_ref;
if(ADC_Chanul_Turn%20) //外部基准电压
{
temp1=ADC_RES; //获取转换结果
ADC_1Data=((double)temp1/256)*5; //取八位计算基准电压Data
adc1 = ADC_1Data;
}
if(ADC_Chanul_Turn%2
1)
{
temp0=ADC_RES; //获取转换结果
ADC_0Data=((double)temp0/256)*5; //取八位计算实际值Data
adc0 =ADC_0Data;
}

ADC_CONTR = ADC_POWER | ADC_SPEEDH | ADC_START | ADC_Chanul_Turn;
ADC_Chanul_Turn++;
if(ADC_Chanul_Turn==2)
ADC_Chanul_Turn=0;
}

/----------------------------
Initial ADC sfr
----------------------------
/
void Init_ADC()
{
P1ASF = 0x03; //Set all P1 as analog input port
ADC_RES = 0; //Clear previous result
// ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | ch;
if(ADC_Chanul_Turn%20)//外部基准电压
{
ADC_CONTR=0xF0; //AD转换控制器,1111,0000 P10口
nop();
nop();
nop();
nop();
ADC_CONTR=0xE8; //1110,1000 (清0flag,置位start)
}
if(ADC_Chanul_Turn%2
1)
{
ADC_CONTR=0xF1; // 1111,0001 P11口
nop();
nop();
nop();
nop();
ADC_CONTR=0xE9; //1110,1001
}
delay_1ms(20); //ADC power-on delay and Start A/D conversion
}
预查看下载完整代码请见51黑论坛:STC12系列单片机ADC中断使用
http://www.51hei.com/bbs/dpj-203492-1.html
(出处: http://www.51hei.com/bbs/)

猜你喜欢

转载自blog.csdn.net/weixin_44080304/article/details/114676196
ADC
今日推荐