社区导航

 
查看: 211|回复: 3

[分享] 基于MSP430简易示波器的设计电路与程序

[复制链接]

344

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2018-11-9 07:48:25 | 显示全部楼层 |阅读模式
本帖最后由 alan000345 于 2018-11-9 10:15 编辑

1.硬件设计
1.1 单片机
选用MSP430G2553单片机,该单片机具有低功耗的特点,内部自带8路10位AD转换器(ADC10),最高主频可达16Mhz,对于一个简易示波器来说这些特点足够我们使用。
1.2 程控放大电路
程控放大电路的作用是对大信号进行衰减,对小信号进行放大,保证输入到A/D转换器的信号幅度在要求的输入电压范围内,以达到最好的测量与观察效果。采用模拟开关CD4051,配合精密电位器实现多挡垂直分辨率。在MSP430单片机中使用寄存器模块设置通道号,通过写入通道号控制模拟开关选通不同的反馈电阻,从而实现不同的放大倍数,对信号进行不同程度的放大(衰减)。电路图如下:
82.001.jpg


1.3 简易调理电路
由于示波器观察信号大多是正负电压信号,考虑到ADC10一般使用的是单极性参考电压(也可以使用寄存器设置双极性参考电压,这样就不需要调理电路了,但最好加一级缓冲)。为了采样到信号的负电压,就需要给该信号叠加直流量,将负电压部分信号抬高至零电平以上,因此采用信号调理电路。电路图如下:

82.002.jpg


1.4 LCD显示电路和按键电路
利用LCD的SPI通信模式与MSP430单片机连接,这样可以得到不错的通信速度,并且可以尽可能的减少MSP430引脚的占用,具体电路这里就不给出了。(按照spi连接)
利用简单独立按键实现放大倍数调节,采样频率设置等功能即可。
2.软件设计
2.1 单片机初始化
对P2口初始化,打开P2口的中断;将通信方式设置为硬件spi通信模式(注意spi通信在上升沿还是在下降沿开始)。
                            WDTCTL=WDTPW+WDTHOLD; //关看门狗

                            P1OUT = 0x00;                             // P1 setup for LED & reset output
                P1DIR |= BIT0 + BIT2 + BIT3 + BIT4 + BIT5;
                P1SEL = BIT1 + BIT2 + BIT4;
                P1SEL2 = BIT1 + BIT2 + BIT4;
                P2REN |= 0x38;
                  P2DIR = 0x07;
                  P2OUT = 0;
                  P2IE |= 0x38;                             // P1.4 interrupt enabled
                  P2IFG &= ~0x38;
                  will=0;
                UCA0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC + UCCKPH ;  // 3-pin, 8-bit SPI master
                UCA0CTL1 |= UCSSEL_2;                     // SMCLK
                UCA0BR0 |= 0x04;                          // /2
                UCA0BR1 = 0;                              //
                UCA0MCTL = 0;                             // No modulation
                UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
                P1OUT &= ~BIT5;                           // Now with SPI signals initialized,
                P1OUT |= BIT5;                            // reset slave
ADC10初始化,开启参考源和中断。
              ADC10CTL0 = ADC10SHT_0 + REFON + ADC10ON + ADC10IE;
              ADC10CTL1 = INCH_6;
ADC10AE0 |= 0x40;  
显示初始化,对LCD的界面显示初始化。
Initial_ILI9340C();
                            Delay_ms(300);
                            LCD_TEST_SingleColor(Black);
                            LCD_TEST_SingleColor(Black);
                            LCD_TEST_PartColor(Blue);
                            for(wh=22; wh<220 ;wh+=10)
                            {
                                          LCD_draw_Line(wh,39,White);
                                          LCD_draw_Line(wh,79,White);
                                          LCD_draw_Line(wh,119,White);
                                          LCD_draw_Line(wh,159,White);
                                          LCD_draw_Line(wh,199,White);
                                          LCD_draw_Line(wh,239,White);
                                          LCD_draw_Line(wh,279,White);
                            }
                            Delay_ms(100);
                            for(co=2; co<320 ;co+=10)
                            {
                                          LCD_draw_Col(69,co,White);
                                          LCD_draw_Col(119,co,White);
                                          LCD_draw_Col(169,co,White);
                            }
                            Delay_ms(100);
复制代码

2.2 程控选择程序
根据按键的次数,在P2口中断改变will的值,并通过P2口输出给CD4051的ABC开关选择端,对放大倍数进行选择。
              #pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
              if(P2IFG & 0x10)
              {
                            while(0x10 & P2IN);
                            will++;
                            if(will==8)
                            {
                                          will=7;
                            }
              }
              if(P2IFG & 0x20)
              {
                            while(0x20 & P2IN);
                            will--;
                            if(will==255)
                            {
                                          will=0;
                            }
              }
              if(P2IFG & 0x08)
              {
                            while(0x08 & P2IN);
                            chan++;
                            if(chan==4)
                                          chan=0;
              }
    P2IFG &= ~0x38;
    P2OUT=will;
}


2.3 采样频率设置
通过改变ADC10CTL1,通过按键次数对应值不同改变ADC10时钟的频率来调节电路的采样频率。
  switch(chan)
                                                           {
                                                                      case 0: ADC10CTL1 = INCH_6; break;
                                                                      case 1: ADC10CTL1 |= ADC10DIV0 + ADC10DIV1; break;
                                                                      case 2: ADC10CTL1 |= ADC10DIV0 + ADC10DIV2; break;
                                                                      case 3: ADC10CTL1 |= ADC10DIV0 + ADC10DIV1 + ADC10DIV2;                                                                       break;
                                                        }


2.4 软件触发程序
只有在一定条件下才使lcd刷新,保证每次采集到的波形都从一点开始显示,防止由于每次采集到的点不同导致波形一直移动。
ADC10CTL0 |= ENC + ADC10SC;         
  // Sampling and conversion start
                                                        __bis_SR_register(CPUOFF + GIE);      
                                                        if(cir==0) key1 = ADC10MEM/5;
                                                        if(cir==1) key2 = ADC10MEM/5;
                                                        if(cir==2) key3 = ADC10MEM/5;
                                                        if(cir>2 && key1>key2 && key2>key3)  //((key1-100)/2)>=(key2-100)
                                                        {
                                                                      temp[0]=key1;
                                                                      temp[1]=key2;
                                                                      temp[2]=key3;
                                                                      temp[cir]=ADC10MEM/5;
                                                        }
                                          ADC10CTL0 &= ~ENC;
2.5 显示刷新程序
示波器是一个动态显示过程,因此在过程中可能会引起初始界面被部分覆盖,以此需要定时刷新初始界面。
trig++;

                                          if(trig%20==0)
                                          {
                                                        for(wh=22; wh<220 ;wh+=10)
                                                        {
                                                                      LCD_draw_Line(wh,39,White);
                                                                      LCD_draw_Line(wh,79,White);
                                                                      LCD_draw_Line(wh,119,White);
                                                                      LCD_draw_Line(wh,159,White);
                                                                      LCD_draw_Line(wh,199,White);
                                                                      LCD_draw_Line(wh,239,White);
                                                                      LCD_draw_Line(wh,279,White);
                                                        }
                                                        Delay_ms(300);
                                                        for(co=2; co<320 ;co+=10)
                                                        {
                                                                      LCD_draw_Col(69,co,White);
                                                                      LCD_draw_Col(119,co,White);
                                                                      LCD_draw_Col(169,co,White);
                                                        }
                                                        Delay_ms(300);
                                          }
附:源程序

#include "msp430g2553.h" //STC12单片机头文件

//颜色定义
#define Blue                             0x001f
#define Yellow                            0xffe0
#define Green                             0x07e0
#define Black                            0x0000
#define White                            0xffff
#define Red                                          0xf800

//引脚定义
#define              R_ESET1 P1OUT|=BIT5; //液晶RESET引脚,接单片机IO引脚
#define R_ESET0 P1OUT&=~BIT5;
#define              C_D1              P1OUT|=BIT3;//液晶D/CX引脚,数据/命令控制,接单片机IO引脚
#define              C_D0                 P1OUT&=~BIT3;
#define              C_S1                 P1OUT|=BIT0;//液晶片选CS,P1.4为单片机SPI总线的SS引脚,通过MSTR位配置为IO模式
#define              C_S0                 P1OUT&=~BIT0;

unsigned char MST_Data, SLV_Data, wh, temp[320], trig=0, key1, key2 ,key3 ,will ,chan=0;
unsigned int co,cir;


void delay(void)
{
unsigned int j;
  for(j=100;j>0;j--);
}
void Delay_us(int value)////延时函数_us
              {
              while (value)
              value--;
              }

void Delay_ms(int value)////延时函数_ms
              {
              while (value){
                            Delay_us(999);
                            value--;
                            }
              }

void LCD_Writ_Bus(char a){   //数据写入函数 8位
      C_S0;
      UCA0TXBUF = a;
      __delay_cycles(50);
      while (!(IFG2 & UCA0TXIFG));
      C_S1;

}

void LCD_WRITE_CMD(char cmd){//8 bit
      C_D0;
      LCD_Writ_Bus(cmd);
}

void LCD_WRITE_COM_DATA(char com_data){//8 bit
      C_D1;
      LCD_Writ_Bus(com_data);
}

void LCD_WRITE_DATA(int a){//16位数据,分两次,每次送8位
      C_D1;
      LCD_Writ_Bus(a>>8);
                LCD_Writ_Bus(a);
}

//设置绘点窗口,x=0~239,y=0~319
void Address_set(unsigned int x1,unsigned int x2,unsigned int y1,unsigned int y2)
{
                   LCD_WRITE_CMD(0x2a);               //x轴
                   LCD_WRITE_DATA(x1);
                   LCD_WRITE_DATA(x2);
                  LCD_WRITE_CMD(0x2b);               //y轴
                  LCD_WRITE_DATA(y1);
                   LCD_WRITE_DATA(y2);
                   LCD_WRITE_CMD(0x2c);
}

void LCD_TEST_SingleColor(int Discolor){
                   int i,j;
                            Address_set(0,239,0,319);

                            for (i=0;i<320;i++){
                                          for (j=0;j<240;j++){
                                                        LCD_WRITE_DATA(Discolor);
                                                        }
                            }
}

void LCD_TEST_PartColor(int Discolor){
                   int i,j;
                            Address_set(0,19,0,319);

                            for (i=0;i<320;i++){
                                          for (j=0;j<20;j++){
                                                        LCD_WRITE_DATA(Discolor);
                                                        }
                            }
                            Address_set(220,239,0,319);

                            for (i=0;i<320;i++){
                                          for (j=220;j<240;j++){
                                                        LCD_WRITE_DATA(Discolor);
                                                        }
                            }
}

//画一条横线
void LCD_draw_Line(unsigned int x,unsigned int y,unsigned int color)
{                            int i;
                            Address_set(x,x+4,y,y);
                            for (i=0;i<5;i++){
                                          LCD_WRITE_DATA(color);
                                          }
}

void LCD_draw_Col(unsigned int x,unsigned int y,unsigned int color)
{                            int i;
                            Address_set(x,x,y,y+4);
                            for (i=0;i<5;i++){
                                          LCD_WRITE_DATA(color);
                                          }
}

//液晶主控初始化
void Initial_ILI9340C(void)
{
        LCD_WRITE_CMD(0xCB);
        LCD_WRITE_COM_DATA(0x39);
        LCD_WRITE_COM_DATA(0x2C);
        LCD_WRITE_COM_DATA(0x00);
        LCD_WRITE_COM_DATA(0x34);
        LCD_WRITE_COM_DATA(0x02);

        LCD_WRITE_CMD(0xCF);
        LCD_WRITE_COM_DATA(0x00);
        LCD_WRITE_COM_DATA(0XC1);
        LCD_WRITE_COM_DATA(0X30);

        LCD_WRITE_CMD(0xE8);
        LCD_WRITE_COM_DATA(0x85);
        LCD_WRITE_COM_DATA(0x00);
        LCD_WRITE_COM_DATA(0x78);

        LCD_WRITE_CMD(0xEA);
        LCD_WRITE_COM_DATA(0x00);
        LCD_WRITE_COM_DATA(0x00);

        LCD_WRITE_CMD(0xED);
        LCD_WRITE_COM_DATA(0x64);
        LCD_WRITE_COM_DATA(0x03);
        LCD_WRITE_COM_DATA(0X12);
        LCD_WRITE_COM_DATA(0X81);

        LCD_WRITE_CMD(0xF7);
        LCD_WRITE_COM_DATA(0x20);

        LCD_WRITE_CMD(0xC0);    //Power control
        LCD_WRITE_COM_DATA(0x23);   //VRH[5:0]

        LCD_WRITE_CMD(0xC1);    //Power control
        LCD_WRITE_COM_DATA(0x10);   //SAP[2:0];BT[3:0]

        LCD_WRITE_CMD(0xC5);    //VCM control
        LCD_WRITE_COM_DATA(0x3e); //对比度调节
        LCD_WRITE_COM_DATA(0x28);

        LCD_WRITE_CMD(0xC7);    //VCM control2
        LCD_WRITE_COM_DATA(0x86);  //--

        LCD_WRITE_CMD(0x36);    // Memory Access Control
        LCD_WRITE_COM_DATA(0xC8);

        LCD_WRITE_CMD(0x3A);
        LCD_WRITE_COM_DATA(0x55);

        LCD_WRITE_CMD(0xB1);
        LCD_WRITE_COM_DATA(0x00);
        LCD_WRITE_COM_DATA(0x18);

        LCD_WRITE_CMD(0xB6);    // Display Function Control
        LCD_WRITE_COM_DATA(0x08);
        LCD_WRITE_COM_DATA(0x82);
        LCD_WRITE_COM_DATA(0x27);

        LCD_WRITE_CMD(0xF2);    // 3Gamma Function Disable
        LCD_WRITE_COM_DATA(0x00);

        LCD_WRITE_CMD(0x26);    //Gamma curve selected
        LCD_WRITE_COM_DATA(0x01);

        LCD_WRITE_CMD(0xE0);    //Set Gamma
        LCD_WRITE_COM_DATA(0x0F);
        LCD_WRITE_COM_DATA(0x31);
        LCD_WRITE_COM_DATA(0x2B);
        LCD_WRITE_COM_DATA(0x0C);
        LCD_WRITE_COM_DATA(0x0E);
        LCD_WRITE_COM_DATA(0x08);
        LCD_WRITE_COM_DATA(0x4E);
        LCD_WRITE_COM_DATA(0xF1);
        LCD_WRITE_COM_DATA(0x37);
        LCD_WRITE_COM_DATA(0x07);
        LCD_WRITE_COM_DATA(0x10);
        LCD_WRITE_COM_DATA(0x03);
        LCD_WRITE_COM_DATA(0x0E);
        LCD_WRITE_COM_DATA(0x09);
        LCD_WRITE_COM_DATA(0x00);

        LCD_WRITE_CMD(0XE1);    //Set Gamma
        LCD_WRITE_COM_DATA(0x00);
        LCD_WRITE_COM_DATA(0x0E);
        LCD_WRITE_COM_DATA(0x14);
        LCD_WRITE_COM_DATA(0x03);
        LCD_WRITE_COM_DATA(0x11);
        LCD_WRITE_COM_DATA(0x07);
        LCD_WRITE_COM_DATA(0x31);
        LCD_WRITE_COM_DATA(0xC1);
        LCD_WRITE_COM_DATA(0x48);
        LCD_WRITE_COM_DATA(0x08);
        LCD_WRITE_COM_DATA(0x0F);
        LCD_WRITE_COM_DATA(0x0C);
        LCD_WRITE_COM_DATA(0x31);
        LCD_WRITE_COM_DATA(0x36);
        LCD_WRITE_COM_DATA(0x0F);

        LCD_WRITE_CMD(0x11);    //Exit Sleep
        Delay_ms(120);

        LCD_WRITE_CMD(0x29);    //Display on
        LCD_WRITE_CMD(0x2c);

}

//LCD进入休眠状态
void LCD_Sleep_ILI9340C(void)
{
  LCD_WRITE_CMD(0x28);//Display off
  Delay_ms(20);
  LCD_WRITE_CMD(0x10);//Enter Sleep mode
}
//LCD退出休眠状态
void LCD_ExitSleep_ILI9340C(void)
{
  LCD_WRITE_CMD(0x11);//Exit Sleep
  Delay_ms(120);
  LCD_WRITE_CMD(0x29);//Display on
  LCD_WRITE_CMD(0x2c);
}

void main()
{
                            WDTCTL=WDTPW+WDTHOLD; //关看门狗


                            P1OUT = 0x00;                             // P1 setup for LED & reset output
                P1DIR |= BIT0 + BIT2 + BIT3 + BIT4 + BIT5;
                P1SEL = BIT1 + BIT2 + BIT4;
                P1SEL2 = BIT1 + BIT2 + BIT4;
                P2REN |= 0x38;
                  P2DIR = 0x07;
                  P2OUT = 0;
                  P2IE |= 0x38;                             // P1.4 interrupt enabled
                  P2IFG &= ~0x38;
                  will=0;
                UCA0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC + UCCKPH ;  // 3-pin, 8-bit SPI master
                UCA0CTL1 |= UCSSEL_2;                     // SMCLK
                UCA0BR0 |= 0x04;                          // /2
                UCA0BR1 = 0;                              //
                UCA0MCTL = 0;                             // No modulation
                UCA0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
                P1OUT &= ~BIT5;                           // Now with SPI signals initialized,
                P1OUT |= BIT5;                            // reset slave

                __delay_cycles(75);                 // Wait for slave to initialize

                            Initial_ILI9340C();
                            Delay_ms(300);
                            LCD_TEST_SingleColor(Black);
                            LCD_TEST_SingleColor(Black);
                            LCD_TEST_PartColor(Blue);
                            for(wh=22; wh<220 ;wh+=10)
                            {
                                          LCD_draw_Line(wh,39,White);
                                          LCD_draw_Line(wh,79,White);
                                          LCD_draw_Line(wh,119,White);
                                          LCD_draw_Line(wh,159,White);
                                          LCD_draw_Line(wh,199,White);
                                          LCD_draw_Line(wh,239,White);
                                          LCD_draw_Line(wh,279,White);
                            }
                            Delay_ms(100);
                            for(co=2; co<320 ;co+=10)
                            {
                                          LCD_draw_Col(69,co,White);
                                          LCD_draw_Col(119,co,White);
                                          LCD_draw_Col(169,co,White);
                            }
                            Delay_ms(100);

                            ADC10CTL0 = ADC10SHT_0 + REFON + ADC10ON + ADC10IE;
                 ADC10CTL1 = INCH_6;
                 ADC10AE0 |= 0x40;                         // PA.1 ADC option select

                            while(1)
                            {
                                          for(cir=0;cir<320;cir++)
                                          {
                                                        ADC10CTL0 |= ENC + ADC10SC;             // Sampling and conversion start
                                                        __bis_SR_register(CPUOFF + GIE);        // LPM0, ADC10_ISR will force exi
                                                        if(cir==0) key1 = ADC10MEM/5;
                                                        if(cir==1) key2 = ADC10MEM/5;
                                                        if(cir==2) key3 = ADC10MEM/5;
                                                        if(cir>2 && key1>key2 && key2>key3)  //((key1-100)/2)>=(key2-100)
                                                        {
                                                                      temp[0]=key1;
                                                                      temp[1]=key2;
                                                                      temp[2]=key3;
                                                                      temp[cir]=ADC10MEM/5;
                                                        }
                                                        ADC10CTL0 &= ~ENC;
                                                        switch(chan)
                                                        {
                                                                      case 0: ADC10CTL1 = INCH_6; break;
                                                                      case 1: ADC10CTL1 |= ADC10DIV0 + ADC10DIV1; break;
                                                                      case 2: ADC10CTL1 |= ADC10DIV0 + ADC10DIV2; break;
                                                                      case 3: ADC10CTL1 |= ADC10DIV0 + ADC10DIV1 + ADC10DIV2; break;
                                                        }
                                          }

                                                        for(cir=0;cir<320;cir++)
                                                        {
                                                                      Address_set(20+temp[cir],20+temp[cir],cir,cir);
                                                                      LCD_WRITE_DATA(Yellow);
                                                        }
                                                        Delay_ms(300);
                                                        for(cir=0;cir<320;cir++)
                                                        {
                                                                      Address_set(20+temp[cir],20+temp[cir],cir,cir);
                                                                      LCD_WRITE_DATA(Yellow);
                                                        }
                                                        Delay_ms(300);
                                                        for(cir=0;cir<320;cir++)
                                                        {
                                                                      Address_set(20+temp[cir],20+temp[cir],cir,cir);
                                                                      LCD_WRITE_DATA(Yellow);
                                                        }
                                                        Delay_ms(300);
                                                        for(cir=0;cir<320;cir++)
                                                        {
                                                                      Address_set(20+temp[cir],20+temp[cir],cir,cir);
                                                                      LCD_WRITE_DATA(Yellow);
                                                        }
                                                        Delay_ms(300);
                                                        for(cir=0;cir<320;cir++)
                                                        {
                                                                      Address_set(20+temp[cir],20+temp[cir],cir,cir);
                                                                      LCD_WRITE_DATA(Black);
                                                        }

                                          trig++;

                                          if(trig%20==0)
                                          {
                                                        for(wh=22; wh<220 ;wh+=10)
                                                        {
                                                                      LCD_draw_Line(wh,39,White);
                                                                      LCD_draw_Line(wh,79,White);
                                                                      LCD_draw_Line(wh,119,White);
                                                                      LCD_draw_Line(wh,159,White);
                                                                      LCD_draw_Line(wh,199,White);
                                                                      LCD_draw_Line(wh,239,White);
                                                                      LCD_draw_Line(wh,279,White);
                                                        }
                                                        Delay_ms(300);
                                                        for(co=2; co<320 ;co+=10)
                                                        {
                                                                      LCD_draw_Col(69,co,White);
                                                                      LCD_draw_Col(119,co,White);
                                                                      LCD_draw_Col(169,co,White);
                                                        }
                                                        Delay_ms(300);
                                          }
                            }
}
// ADC10 interrupt service routine
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_ISR (void)
{
              __bic_SR_register_on_exit(CPUOFF);        // Clear CPUOFF bit from 0(SR)
}
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
              if(P2IFG & 0x10)
              {
                            while(0x10 & P2IN);
                            will++;
                            if(will==8)
                            {
                                          will=7;
                            }
              }
              if(P2IFG & 0x20)
              {
                            while(0x20 & P2IN);
                            will--;
                            if(will==255)
                            {
                                          will=0;
                            }
              }
              if(P2IFG & 0x08)
              {
                            while(0x08 & P2IN);
                            chan++;
                            if(chan==4)
                                          chan=0;
              }
    P2IFG &= ~0x38;
    P2OUT=will;
}




回复

使用道具 举报

1万

TA的帖子

15

TA的资源

版主

Rank: 6Rank: 6

发表于 2018-11-9 10:01:12 | 显示全部楼层
原理图看不到

点评

谢谢,提醒啊,电路放上去了,没有电路图,软件就不知道咋配置啦  详情 回复 发表于 2018-11-9 10:15
http://shop34182318.taobao.com/


回复

使用道具 举报

344

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2018-11-9 10:15:47 | 显示全部楼层

谢谢,提醒啊,电路放上去了,没有电路图,软件就不知道咋配置啦


回复

使用道具 举报

38

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 7 天前 来自手机 | 显示全部楼层
不错。


回复

使用道具 举报

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

本版积分规则

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

小黑屋|手机版|Archiver|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2018-11-19 17:16 , Processed in 0.133183 second(s), 17 queries , Gzip On, MemCache On.

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