单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1380|回复: 1
收起左侧

基于MS83F0802A的adc转换,io,pwm输出

[复制链接]
liuguonianhua 发表于 2018-9-12 17:32 | 显示全部楼层 |阅读模式
/*                      ----------------
*  VDD-----------|1(VDD)   (GND)8|------------GND
*  RED-----------|2(RA6)   (PA0)7|------------NC
*  GREEN--------|3(PC3)   (PA1)6|------------NC
*  AD6-----------|4(PC2)   (PC4)5|------------PWM
*                       ----------------
*/

//RED,GREEN是共阳led,pwm暂时当做普通IO
//这是一个失败的程序,因为没有达到预期功能,ADC结果寄存器始终数值不变


#include "MS83Fxx02.h"
#include "syscfg.h"

#define _XTAL_FREQ                 4000000
#define red_on     PA6=0;
#define red_off    PA6=1;
#define green_on   PC3=0;
#define green_off  PC3=1;
#define pwm_on     PC4=0;
#define pwm_off    PC4=1;
#define TMR0_NUM       1

void colck_init(void);//所有时钟初始化
void io_init(void);//所有io初始化
void adc_init(void);//adc模块初始化
void Delay_xms(unsigned int x);//延时程序
void start_tran_adc(void);//adc转化程序
float get_adc_value(void);//获取adc转化的数值
float avg_adc_value(int);//平均计算adc转化的值,这样更精确稳定,默认是四次
void act_led(void);//根据adc转化的值处理灯闪烁状态



unsigned int  ADC_time=10; //全局变量,主程序与中断程序间传递数值
float adc_avg_value=0;//作为转灯函数的输入接口




/*********************************************main*****************************************************************************/

void main(void)
{
        CLRWDT();
    colck_init();
    io_init();
    adc_init();

   while(ADC_time>1000)//time0每溢出一次ADC_time增加一次
    {
                CLRWDT();
                ADC_time=0;
            adc_avg_value=0;
        adc_avg_value=avg_adc_value(4);
        act_led();
    }


}

/*********************************************************************************************************************/







void colck_init(void)
{
    //UCFG0
////////关键数据//////////////
    OPTION=0B00001000;//time0定时器,PORTA上拉使能,PC1下降沿中断,内部时钟,预分频器给看门狗使用,1:1分频
    OSCCON=0B11010011;//低频,256Khz,timer0每一指令周期加1,2M系统时钟focs
    WDTCON=0B00010111;//看门狗时钟源32khz,65565分频,溢出周期为32khz/65535,软件打开看门狗(sbit<0>)
    ADCON1=0B10110000;//256Khz转换时钟
////////关键数据//////////////*


    //T1CON=0B10000101;//time1定时器,高电平有效,1:1分频,内部时钟
    //T2CON&=0B11111000;//time2定时器关闭
    /*全局中断及time1中断在此设置*/

    INTCON|=0B10100000;//全局中断使能


}

void io_init(void)
{
     //GPIO 设置为输出时,弱上拉会自动关断,此点可作为测试关键点
    CMCON0=0B00000111;//关闭PA6引脚的比较模式
    MSCKCON=0B00000000;

     TRISA=0B00000000;//全部porta引脚配置为输出
      TRISC=0B00000100;//除PC2配置为AN输入外,其他全部配置为输入
      PORTA=0B00000000;//初始化porta端口,全部低电平
      PORTC=0B00000000;//初始化portc端口,全部低电平
      ANSEL=0B01000000;//除AN6通道为模拟输入外,其他全部设置为数字IO

       WPUA=0B10111111;//PORTA6外,全部弱上拉使能
       WPUC=0B00000000;//上拉外,其余pc2端口全部允许弱上拉
        WPD=0B00000100;//除pc2为an6通道设置为下拉外,PA4,PC1,PC3都不
}


void adc_init(void)
{
    ADCON0=0B10111000;//右对齐,内部2v参考电压,AN6模拟通道,转换完成,禁止ADC开始(sbit<0>)
        //ADCON0=0B10111100;//1/4VDD an7
}



void start_tran_adc(void)
{
    if(!GO_DONE)
    {
        CLRWDT();
        ADIF=0;//adc中断标志位清零
        ADON=1;//转换使能开启,允许ADC转换
        Delay_xms(20);//等待使能稳定
        GO_DONE=1;//开始转换
        while(GO_DONE)//如果转换未完成,等待
                CLRWDT();
        ADON=0;//如果转换完成,将转换使能关闭,结束本次转换
    }
}


float get_adc_value(void)//获取adc转换结果寄存器数据
{
   CLRWDT();
   int ADC_num=0;
   float ADC_value=0.0;
    ADC_num=ADRESH;
    ADC_num=ADC_num<<8;
    ADC_num=ADC_num|ADRESL;
    ADC_value=(ADC_num/1023)*2.0;//参考电压为内部2v,如果想要改变参考电压,在ADCON0寄存器修改
    return ADC_value;
}

float avg_adc_value(int avg_init)//平均多次转换结果,使转换结果更稳定
{
        CLRWDT();
        float value_tmp=0;
        for(int T=0;T<avg_init;T++)
        {
                start_tran_adc();
                CLRWDT();
        value_tmp+=get_adc_value();
        }
        return (value_tmp/avg_init);
}




void act_led(void)//根据adc转换的平均结果控制闪灯
{
    CLRWDT();
    float tmp=adc_avg_value;
    if(tmp>=4.16)//大于4.16v充满,绿灯常亮
    {
        //{red_off;pwm_off;}
        green_on;
    }
    else if(tmp>=3.0&&tmp<4.16)//3.0v~4.16v快充阶段,绿灯常亮,红灯快闪
    {
        //pwm_off;
                green_on;
        for(int cir=0;cir<50;cir++)
        {
            red_on;Delay_xms(500);red_off;Delay_xms(250);
        }

    }
    else if(tmp>=0&&tmp<3.0)//0v~3.0v涓充阶段,红灯慢闪
    {
       // {green_off;pwm_off;}
        for(int cir=0;cir<50;cir++)
        {
            red_on;Delay_xms(2000);red_off;Delay_xms(1000);
        }
    }
    else//小于0以及其它状态pwm常亮
    {
        CLRWDT();
        //{green_off;red_off;}
                pwm_on;
        Delay_xms(100);
    }



}


void Delay_xms(unsigned int x)
{
          unsigned int i;
        for(i=0;i<x;i++)
        {
                __delay_ms(1);
                CLRWDT();
                }
}


void interrupt ISR(void){
        if(T0IE&&T0IF==1){
                T0IF=0;
                TMR0=TMR0_NUM;//赋初值
                ADC_time++;

        }
}
/////////////////////////////////////////////



原理图

原理图

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

bsqpcb 发表于 2018-12-17 23:20 | 显示全部楼层
这个芯片稳定
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机 联系QQ:125739409;技术交流QQ群582644647

Powered by 单片机教程网

快速回复 返回顶部 返回列表