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

alan000345   2018-11-9 07:48 楼主
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; } 本帖最后由 alan000345 于 2018-11-9 10:15 编辑

回复评论 (3)

原理图看不到
http://shop34182318.taobao.com/ https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr
点赞  2018-11-9 10:01
引用: ddllxxrr 发表于 2018-11-9 10:01
原理图看不到

谢谢,提醒啊,电路放上去了,没有电路图,软件就不知道咋配置啦
点赞  2018-11-9 10:15
不错。
点赞  2018-11-12 22:46
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复