找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 542|回复: 0
打印 上一主题 下一主题
收起左侧

基于STM32单片机数字电压表自动切换量程及源程序

[复制链接]
跳转到指定楼层
楼主
一、系统方案
1、本设计采用这STM32单片机作为主控器。
2、液晶1602显示。
3、内部ADC采集电压0-12V,自动切换档位。


二、硬件设计
原理图如下:

三、单片机软件设计
1、首先是系统初始化
u8 i;
         u16 a,b,c,d;
        u16 adcx;
        float adc;
        unsigned char  datas[4];
        InitGPIO();
        LcdInit();
        Adc_Init();

        LcdWriteCom(0xc0);  //设置数据指针起点

        for(i=0;i<16;i++)
        {
                LcdWriteData(Disp_Vol[i ]);
        }                 

2、液晶显示程序
/*******************************************************************************
* 函 数 名         : LcdWriteCom
* 函数功能                   : 向LCD写入一个字节的命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
void LcdWriteCom(uchar com)          //写入命令
{
//        LCD1602_E = 0;     //使能
        GPIO_ResetBits(GPIOB,GPIO_Pin_3);
//        LCD1602_RS = 0;           //选择发送命令
        GPIO_ResetBits(GPIOB,GPIO_Pin_1);
//        LCD1602_RW = 0;           //选择写入
        GPIO_ResetBits(GPIOB,GPIO_Pin_2);
//        LCD1602_DATAPINS = com;     //放入命令
        GPIO_Write(GPIOC,0X00FF&com);
        Lcd1602_Delay1ms(1);                //等待数据稳定
//        LCD1602_E = 1;                  //写入时序
        GPIO_SetBits(GPIOB,GPIO_Pin_3);
        Lcd1602_Delay1ms(5);          //保持时间
//        LCD1602_E = 0;
        GPIO_ResetBits(GPIOB,GPIO_Pin_3);        
}
/*******************************************************************************
* 函 数 名         : LcdWriteData
* 函数功能                   : 向LCD写入一个字节的数据
* 输    入         : dat
* 输    出         : 无
*******************************************************************************/
void LcdWriteData(uchar dat)                        //写入数据
{
//        LCD1602_E = 0;        //使能清零
        GPIO_ResetBits(GPIOB,GPIO_Pin_3);        
//        LCD1602_RS = 1;        //选择输入数据
        GPIO_SetBits(GPIOB,GPIO_Pin_1);        
//        LCD1602_RW = 0;        //选择写入
        GPIO_ResetBits(GPIOB,GPIO_Pin_2);
//        LCD1602_DATAPINS = dat; //写入数据
        GPIO_Write(GPIOC,0X00FF&dat);        
        Lcd1602_Delay1ms(1);

//        LCD1602_E = 1;   //写入时序
        GPIO_SetBits(GPIOB,GPIO_Pin_3);        
        Lcd1602_Delay1ms(5);   //保持时间
//        LCD1602_E = 0;
        GPIO_ResetBits(GPIOB,GPIO_Pin_3);               
}
3、ADC程序
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{
          //设置指定ADC的规则组通道,一个序列,采样时间
        ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期                                      

        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能        

        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

        return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
        u32 temp_val=0;
        u8 t;
        for(t=0;t<times;t++)
        {
                temp_val+=Get_Adc(ch);
                delay_ms(5);
        }
        return temp_val/times;
}         

4、核心算法程序
int main(void)
{        
  u8 i;
         u16 a,b,c,d;
        u16 adcx;
        float adc;
        unsigned char  datas[4];
        InitGPIO();
        LcdInit();
        Adc_Init();

        LcdWriteCom(0xc0);  //设置数据指针起点

        for(i=0;i<16;i++)
        {
                LcdWriteData(Disp_Vol[i ]);
        }                 
        while(1)
        {
                adcx=Get_Adc_Average(ADC_Channel_1,10);
                adc=(float)adcx*(5.0/4096);
                adcx=adc;
                a=adcx;
                adc-=adcx;
                adcx=adc*100;  //1位有效数字
                b=adcx;
                c=a*100+b;
                d=c*24/10;
                if(d<500)
                {
                        LcdWriteCom(0x80);  //设置数据指针起点
                        for(i=0;i<16;i++)
                        {
                                LcdWriteData(Disp_Vol1[i ]);
                        }        
                }
                else
                {
                  LcdWriteCom(0x80);  //设置数据指针起点
                        for(i=0;i<16;i++)
                        {
                                LcdWriteData(Disp_Vol2[i ]);
                        }        
                }        
                LcdWriteCom(0xc9);
                LcdWriteData('0'+d/1000);
                        LcdWriteData('0'+d%1000/100);
                LcdWriteCom(0xcc);
                LcdWriteData('0'+d%1000%100/10);
                LcdWriteData('0'+d%10);

        }

}

四、 proteus仿真设计
Proteus软件是一款应用比较广泛的工具,它可以在没有硬件平台的基础上通过自身的软件仿真出硬件平台的运行情况,这样就可以通过软件仿真来验证我们设计的方案有没有问题,如果有问题,可以重新选择器件,连接器件,直到达到我们设定的目的,避免我们搭建实物的时候,如果当初选择的方案有问题,我们器件都已经焊接好了,再去卸载下去,再去焊接新的方案的器件,测试,这样会浪费人力和物力,也给开发者带来一定困惑,Proteus仿真软件就很好的解决这个问题,我们在设计之初,就使用该软件进行模拟仿真,测试,选择满足我们设计的最优方案。最后根据测试没问题的仿真图纸,焊接实物,调试,最终完成本设计的作品。

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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