本帖最后由 dirtwillfly 于 2015-1-23 22:08 编辑
一:本设计基于MSP430G2231为核心控制系统,结合适量的硬件设计,配合12864液晶,制作出一个自动量程的电压,电阻,温度测试仪表。电压量程在0-11V,电阻档量程:0-100kΩ,温度适于室温测量。此表多适用于电子DIY爱好者使用。
二:原理
当被测电压
VDD时,由上图可知,我们只需测出V值,即可知道VDD值。VDD=V*(R9+R10)/R10.而V的值可用430的ADC采集得到。
2. 电阻测量:
原理和电压测量一样当VDD已知,R10已知,V已知时。R9的阻值:R9=(VDD/V-1)*R10。3:温度测量:基于18B20。DS1820 数字温度计以9 位数字量的形式反映器件的温度值。DS1820 通过一个单线接口发送或接收信息,因此在中央微处理器和DS1820 之间仅需一条连接线(加上地线)。用于读写和温度转换的电源可以从数据线本身获得,无需外部电源。因为每个 DS1820 都有一个独特的片序列号,所以多只DS1820 可以同时连在一根单线总线上,这样就可以把温度传感器放在许多不同的地方。这一特性在HVAC 环境控制、探测建筑物、仪器或机器的温度以及过程监测和控制等方面非常有用。整体设计思路
三:电路实现
1:电阻与电压测量外围硬件电路图,电压测量时,高电位端接红表笔,低电位端接黑表笔。通过运放的电压跟随,解决了数字万用表仅使用于测量恒压源的窘境,但同时也由于运放的限制,测量电压范围变小。当测量电压低于2V时,ADC0采集的电压值有效,作为测量值,而ADC1采样无效。每次测量都是由大量程开始,通过程序判断,该量程是否合适,如量程太大,进行小量程切换。 2:电阻的测量是本设计的经典,不借助于模拟开关,手动开关选档。而借助于单片机IO口的上拉输出,高阻态输入完成自动选档。如当P12为高电平时,P13为高阻态时,R5与被测电阻形成通路分IO口电压,然后再经358跟随供AD采集。通过切换P12,P13的输入输出状态即可实现档位切换。
18B20具有很多优秀的特性,如零待机功耗,独特的单线接口仅需一个端口引脚进行通讯,报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件。3:电源模块 因为用的是MSP430的LAUNCHPAD开发板,故3,5V供电电压不用单独制作。只需产生运放需要要的12V电压,本设计依赖34063的芯片的升压,由5V升到12V。
4:液晶显示模块
此设计也是经典之举,尽管抬高了此作品的造价,因430总共只有10个可操控IO口,而一般的显示模块都得用8个左右,而用12864的串行模式,同时运用MSP430的SPI通信,既方便又高效的完成了液晶显示的操作。同时采用5分钟定时息屏操作,从根本上解决了低功耗的问题,环保,节约。关于12864这里不再赘述。 4:按键模块
因为设计温度是一直显示,所以就只需对电阻,电压进行选择。所以运用了两个按键作为人际交互手段,而复位按键由MSP430开发板自身提供。实物图
源码:
- /*
- * main.c
- */
- #include <msp430.h>
- typedef struct REG{
- unsigned bit0 : 1;
- unsigned bit1 : 1;
- unsigned bit2 : 1;
- unsigned bit3 : 1;
- unsigned bit4 : 1;
- unsigned bit5 : 1;
- unsigned bit6 : 1;
- unsigned bit7 : 1;
- }REG;
- typedef enum STATE{
- WELCOME = 1,
- VOLTAGE,
- RESISTANCE
- }STATE;
- #define uchar unsigned char
- #define uint unsigned int
- #define jump_ROM 0xCC
- #define start 0x44
- #define read_EEROM 0xBE
- typedef unsigned char byte;
- typedef unsigned int word;
- #define N_SAMPLE 12
- #define P1 ((REG *) 0x0021)
- #define RS P1->bit7
- #define DQ P1->bit4 //DS18B20数据口
- void dispnum(unsigned int a,unsigned char x,unsigned char y) ;
- void dispuserset(unsigned int a,unsigned char x,unsigned char y);
- volatile STATE state = WELCOME;
- word adc_value[N_SAMPLE];
- unsigned char TMPH,TMPL;
- void Key_Init(void)
- {
- P2SEL &= ~BIT6 + ~BIT7;
- P2REN |= BIT6 + BIT7;
- P2OUT |= BIT6 + BIT7;
- P2IE |= BIT6 + BIT7;
- P2IES |= BIT6 + BIT7;
- P2IFG &= ~BIT6 + ~BIT7;
- }
- void TimerA0_Init(void)
- {
- TACCR0 = 30000;
- TACCR1 = 20000;
- TACTL = TASSEL_2 + MC_2 + ID_3;
- TACCTL1 = CCIE;
- TACTL |= TACLR;
- }
- void ADC_Init(void)
- {
- ADC10CTL1 = CONSEQ_2;
- ADC10CTL0 = ADC10SHT_2 + MSC + ADC10ON + ADC10IE;
- ADC10DTC1 = N_SAMPLE;
- ADC10SA = (word) adc_value;
- }
- void ADC_Channel_Select(word channel)
- {
- ADC10CTL1 &= 0x0fff;
- ADC10CTL1 |= channel;
- ADC10AE0 &= 0x00;
- ADC10AE0 = (1 << (channel >> 12));
- }
-
- inline void SPI_Init(void)
- {
- USICTL0 |= USIPE6 + USIPE5 + USIMST + USIOE;
- USICTL1 |= USICKPH + USIIE;
- USICKCTL = USIDIV_4 + USISSEL_2;
- USICTL0 &= ~USISWRST;
- __enable_interrupt();
- }
- void SPI_Transmit(byte data)
- {
- USISRL = data;
- USICNT = 8;
- // while (!(USIIFG & USICTL1));
- LPM0;
- }
- /********************************************************************
- * 名称 : delay()
- * 功能 : 延时函数
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void delay(unsigned int yN)
- {
- unsigned int i;
- for(i=0; i<yN; i++)
- ;
- }
- /********************************************************************
- * 名称 : Reset()
- * 功能 : 复位DS18B20
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- uchar Reset(void)
- {
- uchar deceive_ready;
- DQ = 0;
- delay(29);
- DQ = 1;
- delay(3);
- deceive_ready = DQ;
- delay(25);
- return(deceive_ready);
- }
- /********************************************************************
- * 名称 : read_bit()
- * 功能 : 从DS18B20读一个位值
- * 输入 : 无
- * 输出 : 从DS18B20读出的一个位值
- ***********************************************************************/
- uchar read_bit(void)
- {
- uchar i;
- DQ = 0;
- DQ = 1;
- for(i=0; i<3; i++);
- return(DQ);
- }
- /********************************************************************
- * 名称 : write_bit()
- * 功能 : 向DS18B20写一位
- * 输入 : bitval(要对DS18B20写入的位值)
- * 输出 : 无
- ***********************************************************************/
- void write_bit(uchar bitval)
- {
- DQ=0;if(bitval==1)
- DQ=1;
- delay(5);
- DQ=1;
- }
- /********************************************************************
- * 名称 : read_byte()
- * 功能 : 从DS18B20读一个字节
- * 输入 : 无
- * 输出 : 从DS18B20读到的值
- ***********************************************************************/
- uchar read_byte(void)
- {
- uchar i,m,receive_data;
- m = 1;
- receive_data = 0;
- for(i=0; i<8; i++)
- {
- if(read_bit())
- {
- receive_data = receive_data + (m << i);
- }
- delay(6);
- }
- return(receive_data);
- }
- /********************************************************************
- * 名称 : write_byte()
- * 功能 : 向DS18B20写一个字节
- * 输入 : val(要对DS18B20写入的命令值)
- * 输出 : 无
- ***********************************************************************/
- void write_byte(uchar val)
- {
- uchar i,temp;
- for(i=0; i<8; i++)
- {
- temp = val >> i;
- temp = temp & 0x01;
- write_bit(temp);
- delay(5);
- }
- }
- /********************************************************************
- * 名称 : GETDATA()
- * 功能 : 获取数据
- * 输入 : 无
- * 输出 : 温度值,整数
- ***********************************************************************/
- unsigned int GETDATA()
- {
- unsigned int temp;
- DQ = 0;
- Reset();
- write_byte(jump_ROM);
- write_byte(start);
- Reset();
- write_byte(jump_ROM);
- write_byte(read_EEROM);
- TMPL = read_byte();
- TMPH = read_byte();
- temp = TMPL>>4 + 4<<TMPH;
- return temp;
- }
- void LCD_Write_Cmd(byte com)
- {
- RS = 1;
- SPI_Transmit(0xf8);
- SPI_Transmit(0xf0 & com);
- SPI_Transmit(0xf0 & (com << 4));
- RS = 0;
- }
- void LCD_Write_Dat(byte dat)
- {
- RS = 1;
- SPI_Transmit(0xfa);
- SPI_Transmit(0xf0 & dat);
- SPI_Transmit(0xf0 & (dat << 4));
- RS = 0;
- }
- void LCD_Pos(byte x, byte y)
- {
- byte pos;
- switch(x)
- {
- case 0:
- x = 0x80;
- break;
- case 1:
- x = 0x90;
- break;
- case 2:
- x = 0x88;
- break;
- case 3:
- x = 0x98;
- break;
- default:
- break;
- }
- pos = x + y;
- LCD_Write_Cmd(pos);
- }
- void LCD_Init(void)
- {
- LCD_Write_Cmd(0x30);
- LCD_Write_Cmd(0x0c);
- LCD_Write_Cmd(0x01);
- LCD_Write_Cmd(0x02);
- LCD_Write_Cmd(0x80);
- }
- void LCD_Write_Str(byte x, byte y, char *str)
- {
- LCD_Pos(x, y);
- while (*str)
- {
- LCD_Write_Dat(*str++);
- }
- }
- void LCD_Clear_Screen(void)
- {
- LCD_Write_Cmd(0x34);
- LCD_Write_Cmd(0x30);
- LCD_Write_Cmd(0x01);
- }
- void Disp_Welcome_Msg(void)
- {
- LCD_Write_Str(0, 1, "自动量程仪表");
- LCD_Write_Str(1, 0, "温度: °C");
- LCD_Write_Str(2, 0, "1:电阻 2:电压");
- LCD_Write_Str(3, 0, " 欢迎使用");
- }
- word filter(void)
- {
- word ad_val;
- int i;
- for (i = 0; i < N_SAMPLE; i++)
- {
- ad_val += adc_value[i];
- }
- ad_val /= N_SAMPLE;
- return ad_val;
- }
- void Measure_Voltage(void)
- {
- word ad_val = 0;
- byte flag=0;
- LCD_Write_Str(2, 0, " ");
- LCD_Write_Str(2, 0, "电压:");
- LCD_Write_Str(3, 0, " ");
- ADC_Channel_Select(INCH_1);
- ADC10CTL0 &= ~ENC;
- while (ADC10CTL1 & BUSY); // Wait if ADC core is active
- ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
- LPM0;
- ad_val = filter();
- if (ad_val > 150)
- {
- flag=1;
- }
- else
- {
- flag=0;
- ADC_Channel_Select(INCH_2);
- ADC10CTL0 |= ADC10SC;
- LPM0;
- ad_val = filter();
- }
- if(flag==1)
- {
- ad_val=ad_val*1.05;
- dispuserset(ad_val,3,2);
- }
- else
- {
- ad_val=ad_val*3.60;
- dispuserset(ad_val,3,2);
- }
- LCD_Write_Str(3, 4, "V");
- }
- inline void Measure_Resistance(void)
- {
- byte flag=0;
- word ad_val,temp_adc;
- LCD_Write_Str(2, 0, " ");
- LCD_Write_Str(2, 0, "电阻:");
- LCD_Write_Str(3, 0, " ");
- P1DIR |= BIT2;
- P1DIR &= ~BIT3;
- P1OUT |= BIT2;
- ADC_Channel_Select(INCH_0);
- ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
- LPM0;
- ad_val = filter();
- if (ad_val > 150)
- {
- flag=1;
- }
- else
- {
- flag=0;
- P1DIR |= BIT3;
- P1DIR &= ~BIT2;
- P1OUT |= BIT3;
- ADC_Channel_Select(INCH_0);
- ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start
- LPM0;
- ad_val = filter();
- }
- if(flag==1)
- {
- temp_adc=1024-ad_val; //(带小数显示)
- temp_adc=ad_val*10/temp_adc;
- temp_adc=50*temp_adc;
- dispuserset(temp_adc,3,2);
- LCD_Write_Str(3, 4, "KOH");
- }
- else
- {
- temp_adc=1024-ad_val; //(整数显示)
- temp_adc=ad_val*10/temp_adc;
- temp_adc=100*temp_adc;
- dispnum(temp_adc,3,2);
- LCD_Write_Str(3, 4, "OH");
- }
- }
- void main(void) {
- WDTCTL = WDTPW + WDTHOLD;
- P1DIR |= BIT7 + BIT4;
- SPI_Init();
- LCD_Init();
- ADC_Init();
- Key_Init();
- TimerA0_Init();
- P1DIR |= BIT0;
- // Disp_Welcome_Msg();
- for(;;)
- {
- switch(state)
- {
- case WELCOME:
- Disp_Welcome_Msg();
- //dispnum(GETDATA(),1,2);
- break;
- case RESISTANCE:
- Measure_Resistance();
- break;
- case VOLTAGE:
- Measure_Voltage();
- break;
- }
- LPM0;
- }
- }
- #pragma vector = USI_VECTOR
- __interrupt void USI_ISR(void)
- {
- USICTL1 &= ~USIIFG;
- LPM0_EXIT;
- }
- #pragma vector = TIMERA1_VECTOR
- __interrupt void TIMERA1_ISR(void)
- {
- switch(TAIV)
- {
- case 2:
- TACCR1 += 20000;
- LPM0_EXIT;
- break;
- }
- }
- #pragma vector = ADC10_VECTOR
- __interrupt void ADC10_ISR(void)
- {
- LPM0_EXIT;
- }
- #pragma vector = PORT2_VECTOR
- __interrupt void PORT2_ISR(void)
- {
- if (TACCTL0 & CCIFG)
- {
- if (P2IFG & BIT6)
- {
- if (state == VOLTAGE)
- {
- state = WELCOME;
- }
- else
- {
- state = VOLTAGE;
- }
- }
- if (P2IFG & BIT7)
- {
- if (state == RESISTANCE)
- {
- state = WELCOME;
- }
- else
- {
- state = RESISTANCE;
- }
- }
- TACCTL0 &= ~CCIFG;
- TACCR0 += 30000;
- }
- P2IFG &= ~BIT6 + ~BIT7;
- }
- /********************************************************************************/
- void dispnum(unsigned int a,unsigned char x,unsigned char y) //整数显示(4位数-9999)
- {
- unsigned char flag,i=0;
- unsigned char out[5];
- out[0]=' ';
- out[1]=48+(a/1000);
- a=a%1000;
- out[2]=48+(a/100);
- a=a%100;
- out[3]=48+(a/10);
- out[4]=48+(a%10);
- flag=0;
- for(i=1;(i<4)&&(flag==0);i++)
- {
- if(out[i]==48)
- {
- out[i]=32;
- }
- else
- {
- flag=1;
- }
- }
- LCD_Pos( x, y);
- i=0;
- while (i<5)
- {
- LCD_Write_Dat(out[i]);
- i++;
- }
- }
- void dispuserset(unsigned int a,unsigned char x,unsigned char y)//小数显示(2位数+2位小数-99.99)
- {
- unsigned char flag,i=0;
- unsigned char out[5];
- out[0]=48+(a/1000);
- a=a%1000;
- out[1]=48+(a/1000);
- a=a%100;
- out[2]='.';
- out[3]=48+(a/10);
- a=a%10;
- out[4]=48+a;
- flag=0;
- for(i=0;(i<2)&&(flag==0);i++)
- {
- if(out[i]==48)
- {
- out[i]=32;
- }
- else
- {
- flag=1;
- }
- }
- LCD_Pos( x, y);
- i=0;
- while (i<5)
- {
- LCD_Write_Dat(out[i]);
- i++;
- }
- }
复制代码
一周热门 更多>