|
发表于 2012-5-15 10:09:14
|
显示全部楼层
本帖最后由 kejiren123 于 2012-5-15 10:10 编辑
强烈建议logicgreen 大移植到LGT单片机上,如果能出套件相信很多人会买。我愿意出100元买一个LGT单片机的示波器套件(预估材料成本在40-60元)。
我看了,代码不复杂。以下为全部源码。
************************************
Bluetooth Oscilloscope
yus - projectproto.blogspot.com
September 2010
*************************************/
#include "main.h"
_FOSCSEL(FNOSC_FRC); // Select Internal FRC at POR
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF); // Enable Clock Switching and Configure
_FICD(ICS_PGD1 & JTAGEN_OFF);
int main(void)
{
unsigned char c;
osc_init();
port_init();
ser_init();
adc_init();
timer1_init();
//initial values;
ch1_position = 120;
ch2_position = 120;
ch1_gain = VOLT_PER_DIV[4];
ch2_gain = VOLT_PER_DIV[5];
while(1)
{
if(ser_isrx()){
led_off();
c = ser_getch(); //get 1 character from receive buffer
switch(c){
case REQ_DATA:
store_raw_data();
ser_putch(DATA_START);
send_data();
ser_putch(DATA_END);
break;
case ADJ_HORIZONTAL:
c = ser_getch();
if( (c<13) ){ // refer to "timer.h"
set_sampling_period( PERIODS[c] );
}
break;
case ADJ_VERTICAL:
c = ser_getch(); // refer to "adc.h"
if(c==CHANNEL1) ch1_gain = VOLT_PER_DIV[ser_getch()];
else if(c==CHANNEL2) ch2_gain = VOLT_PER_DIV[ser_getch()];
break;
case ADJ_POSITION:
c = ser_getch();
if(c==CHANNEL1) ch1_position = (long)ser_getch() * 6;
else if(c==CHANNEL2) ch2_position = (long)ser_getch() * 6;
break;
default:
break;
} // switch(command)
led_on();
}//if-ser_isrx()
}//while-true
}
void osc_init(void)
{
// Configure PLL prescaler, PLL postscaler, PLL divisor
PLLFBD = 41; // M = 43
CLKDIVbits.PLLPOST=0; // N1 = 2
CLKDIVbits.PLLPRE=0; // N2 = 2
// Initiate Clock Switch to Internal FRC with PLL (NOSC = 0b001)
__builtin_write_OSCCONH(0x01);
__builtin_write_OSCCONL(0x01);
// Wait for Clock switch to occur
while (OSCCONbits.COSC != 0b001);
// Wait for PLL to lock
while(OSCCONbits.LOCK!=1) {};
}
void port_init(void)
{
// LED Pin Configuration:I/O Port RC3; pin 5
PORTCbits.RC3 = 0; // Configure as Output
TRISCbits.TRISC3 = 0; // Configure as Output
LATCbits.LATC3 = 1; // Initialize to zero
RPINR18bits.U1RXR = 28; //RX -> pin 20 (RP28)
RPOR13bits.RP27R = 0b00011; //TX -> pin 19 (RP27)
ADPCFGbits.PCFG4 = 0; // AN4 is configured as analog input
ADPCFGbits.PCFG5 = 0; // AN5 is configured as analog input
}
void send_data(void)
{
#define bits 10
unsigned int i, total;
unsigned int repeat, n;
unsigned char plot_data1, plot_data2;
signed long temp;
total = get_total_samples();
repeat = MAX_SAMPLES / total;
i=0;
while( i<total )
{
/** refer to "adc.xmcd" (mathcad) for the computation
** "zero level" is on Vref/2**/
// CHANNEL 1
temp = (ch1_position<<bits) / (long)MAX_LEVEL;
temp = (long)OFFSET1 + temp - (long)raw_data[i++];
temp = temp * (long)MAX_LEVEL * ch1_gain;
temp = (temp>>bits) + (ch1_position<<2) - (ch1_position*ch1_gain);
temp = temp>>2;
plot_data1 = clamp_value( temp );
// CHANNEL 2
temp = (ch2_position<<bits) / (long)MAX_LEVEL;
temp = (long)OFFSET2 + temp - (long)raw_data[i++];
temp = temp * (long)MAX_LEVEL * ch2_gain;
temp = (temp>>bits) + (ch2_position<<2) - (ch2_position*ch2_gain);
temp = temp>>2;
plot_data2 = clamp_value( temp );
n=repeat;
while(n--){
ser_putch( plot_data1 );
ser_putch( plot_data2 );
}
}
}
unsigned char clamp_value(long value)
{
if(value<0)
return 0;
else if (value>(long)MAX_LEVEL)
return ((unsigned char) MAX_LEVEL);
else
return (unsigned char) value;
}
***********************************************************************************************************************************************
#include "p33fxxxx.h"
#include "adc.h"
#include "timer.h"
volatile unsigned int adc_value_1;
volatile unsigned int adc_value_2;
volatile unsigned int raw_data[MAX_SAMPLES];
volatile unsigned int samples_count;
const long VOLT_PER_DIV[]={
SCALE_10mV,
SCALE_20mV,
SCALE_50mV,
SCALE_100mV,
SCALE_200mV,
SCALE_500mV,
SCALE_1V,
SCALE_2V,
SCALE_GND
};
void adc_init(void)
{
ADCONbits.ADON = 0; // Temporarily Turn off ADC to allow for initialization settings
aux_pll_init();
ADCONbits.FORM = 0; // Output in Integer Format
ADCONbits.EIE = 1; // Enable Early Interrupt (7TAD)
//ADCONbits.ORDER = 0; // Normal Order of conversion
//ADCONbits.SEQSAMP = 0; // Simultaneous sampling
ADCONbits.ASYNCSAMP = 1; // Asynchronous sampling
ADCONbits.SLOWCLK = 0; // High Frequency Clock input (use aux pll)
ADCONbits.ADCS = 0; //5; // Clock divider selection
ADCPC1bits.TRGSRC2 = 0b01100; // Timer1 period match (trigger source)
ADPCFGbits.PCFG4 = 0; // AN4 is configured as analog input
ADPCFGbits.PCFG5 = 0; // AN5 is configured as analog input
IPC28bits.ADCP2IP = 0x01; // Set ADC Pair 2 Interrupt Priority (Level 1)
IFS7bits.ADCP2IF = 0; // Clear ADC Pair 2 Interrupt Flag
//IEC7bits.ADCP2IE = 1; // Enable ADC Pair 2 Interrupt
ADCONbits.ADON = 1; // Enable ADC module
}
/* ADC Pair 2 ISR*/
void __attribute__((interrupt, no_auto_psv)) _ADCP2Interrupt (void)
{
raw_data[samples_count++] = ADCBUF4; // Read AN4 conversion result;
raw_data[samples_count++] = ADCBUF5; // Read AN5 conversion result;
IFS7bits.ADCP2IF = 0; // Clear ADC Pair 2 Interrupt Flag
}
void store_raw_data(void)
{
unsigned int total_samples;
total_samples = get_total_samples();
samples_count = 0; // reset counter
//IEC0bits.U1RXIE = 0; // disable RX interrupt
IEC7bits.ADCP2IE = 1; // enable ADC Pair 2 Interrupt
TMR1 = 0x0000; // reset timer 1
T1CONbits.TON = 1; // Starts 16-bit Timer1
while(samples_count<total_samples); // wait until samples are completed
IEC7bits.ADCP2IE = 0; // disable ADC Pair 2 Interrupt
T1CONbits.TON = 0; // Stops 16-bit Timer1
//IEC0bits.U1RXIE = 1; // Enable RX interrupt
}
unsigned int get_total_samples(void)
{
if(sampling_period==PERIOD_5us)
return (MAX_SAMPLES/4);
else if(sampling_period==PERIOD_10us)
return (MAX_SAMPLES/2);
else
return (MAX_SAMPLES);
}
void aux_pll_init(void)
{
ACLKCONbits.FRCSEL = 1; // Internal FRC is clock source for auxiliary PLL
ACLKCONbits.ENAPLL = 1; // APLL is enabled
ACLKCONbits.SELACLK = 1; // Auxiliary PLL provides the source clock for the clock divider
ACLKCONbits.APSTSCLR = 7; // Auxiliary Clock Output Divider is Divide by 1
while(ACLKCONbits.APLLCK != 1){}; // Wait for Auxiliary PLL to Lock
}
***********************************************************************************************************************************************
#define _SER_C_
#include "p33fxxxx.h"
#include "ser.h"
unsigned char txfifo[SER_BUFFER_SIZE];
volatile unsigned char txiptr, txoptr;
unsigned char rxfifo[SER_BUFFER_SIZE];
volatile unsigned char rxiptr, rxoptr;
unsigned char ser_tmp;
void ser_init(void)
{
//RPINR18bits.U1RXR = 28; //RX -> pin 20 (RP28)
//RPOR13bits.RP27R = 0b00011; //TX -> pin 19 (RP27)
U1MODEbits.STSEL = 0; // 1-stop bit
U1MODEbits.PDSEL = 0; // No Parity, 8-data bits
U1MODEbits.ABAUD = 0; // Auto-Baud Disabled
U1MODEbits.BRGH = 1; //High-Speed mode
U1BRG = BRGVAL; // BAUD Rate Setting
U1STAbits.UTXISEL0 = 0; // Interrupt after one Tx character is transmitted
U1STAbits.UTXISEL1 = 0;
U1STAbits.URXISEL = 0b00; // Interrupt after one RX character is received;
IEC0bits.U1RXIE = 1; //Enable RX interrupt
U1MODEbits.UARTEN = 1; // Enable UART
U1STAbits.UTXEN = 1; // Enable UART Tx
//set ring pointers to empty (zero receive/transmit)
rxiptr=rxoptr=txiptr=txoptr=0;
}
void ser_putch(unsigned char byte)
{
// wait until buffer has an empty slot.
//while (((txiptr+1) & SER_FIFO_MASK)==txoptr)
while (U1STAbits.UTXBF)
continue;
txfifo[txiptr] = byte; //place character in buffer
//increase ring input pointer and set it to zer0 if
//it has rolled-it over.
txiptr=(txiptr+1) & SER_FIFO_MASK;
IEC0bits.U1TXIE = 1; //enable interrupt driven
//serial transmission
}
void ser_puts(unsigned char * s)
{
while(*s) //while pointer s is not at end of string
ser_putch(*s++); // send the current character,
// then increment pointer
}
void ser_puthex(unsigned char v)
{
unsigned char c; //define temp variable
c = v >> 4; //get the high nibble and place it in c
if (c>9) { //if more than 9
ser_putch('A'-10+c); // send the difference from 10 + 'A'
} else { //else
ser_putch('0'+c); // send '0' + the high nibble
}
c = v & 0x0F; //get the lower nibble
if (c>9) { //process the character
ser_putch('A'-10+c); //and send it same as above
} else { //
ser_putch('0'+c); //
}
}
unsigned char ser_isrx(void)
{
if(U1STAbits.OERR) //error in reception?
{
U1STAbits.OERR = 0; //must clear the overrun error to keep uart receiving
return 0; // return no characters in buffer
}
return (rxiptr!=rxoptr); //checks buffer if char is present
}
unsigned char ser_getch(void)
{
unsigned char c; //define
while (ser_isrx()==0) //wait until a character is present
continue; //
c=rxfifo[rxoptr]; //get oldest character received
++rxoptr; //move the pointer to discard buffer
rxoptr &= SER_FIFO_MASK; //if the pointer is at end, roll-it over.
return c; //return it
}
void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt(void)
{
U1TXREG = txfifo[txoptr];
++txoptr;
txoptr &= SER_FIFO_MASK;
if (txoptr==txiptr) IEC0bits.U1TXIE = 0;
}
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void)
{
rxfifo[rxiptr]=U1RXREG;
ser_tmp=(rxiptr+1) & SER_FIFO_MASK;
if (ser_tmp!=rxoptr) rxiptr=ser_tmp;
IFS0bits.U1RXIF = 0;
}
***********************************************************************************************************************************************
#include "p33fxxxx.h"
#include "timer.h"
volatile unsigned int sampling_period;
const unsigned int PERIODS[]={
PERIOD_5us,
PERIOD_10us,
PERIOD_20us,
PERIOD_50us,
PERIOD_100us,
PERIOD_200us,
PERIOD_500us,
PERIOD_1ms,
PERIOD_2ms,
PERIOD_5ms,
PERIOD_10ms,
PERIOD_20ms,
PERIOD_50ms
};
void timer1_init(void)
{
T1CONbits.TON = 0; // Stops 16-bit Timer1
T1CONbits.TCKPS = 0b00; // Timer1 Input Clock Prescale Select bits
T1CONbits.TCS = 0; // Internal clock (FCY)
T1CONbits.TGATE = 0; // Gated time accumulation disabled
set_sampling_period(PERIOD_200us);
//T1CONbits.TON = 1; // Starts 16-bit Timer1
}
void set_sampling_period(unsigned int period)
{
#if 0
PR1 = period;
#else // adc speed limitation
if( (period==PERIOD_5us) || (period==PERIOD_10us) )
PR1 = PERIOD_20us;
else
PR1 = period;
#endif
sampling_period = period;
}
|
|