ใครใจดีช่วยแก้โค๊ด et-base dspic30f2010 การรับค่า ADC แสดงผล LCD ของ จาก W ให้แสดงออกมาเปน V หน่อยครับ
หรือใจดีเขียนให้ใหม่เลยจะขอบคุณมากครับ
ข้อมูล โปรแกรมควบคุม
#include <p30f2010.h>
#define RS LATEbits.LATE4
#define E LATEbits.LATE5
#define RESETSW PORTCbits.RC13
#define RESETSW_PRESSED 0
#define CELL(x) (0x7FFC00+2*(unsigned long)x) // Macro for access to EEPROM cell x(x = 0...511)
//-------------------------- Device Configuration ------------------------
_FOSC(CSW_FSCM_OFF & XT_PLL16);
_FWDT(WDT_OFF);
_FBORPOR(PBOR_ON & BORV_20 & PWRT_64 & MCLR_EN);
//-------------------------- Global Variables ------------------------
unsigned int Samples,Energy,iEEPROM;
long AccPwr,Power;
long long AddE;
//-------------------------- Interrupt Routine ------------------------
void __attribute__((__interrupt__)) _ADCInterrupt(void) // Fs = 50,000 Hz ( 1,000 Samples/Cycle of 50Hz )
{
long DCV,ACA;
unsigned int nEnergy;
IFS0bits.ADIF = 0; // Clear interrupt flag
DCV = (long)ADCBUF1;
ACA = (long)ADCBUF0-512; // AC Amp.
AccPwr += (DCV*ACA);
Samples++; // LSB = Least Significant Value per Bit
if(Samples==1000) { // Pwr(xx.xxx) = AccPwr * 1000 * (LSB of AccPwr) / 1000
Samples=0; // LSB of AccPwr = (LSB of V) * (LSB of A)
if(AccPwr<0) AccPwr=0;
Power=AccPwr/210; // LSB of V = Vpp / (2^n of ADC) = (50) / 1024
AccPwr=0; // LSB of A = App / (2^n of ADC) = (50+50) / 1024
// 210 ~ 209.7152 = 1 / ((50+/1024)*((50+50)/1024))
AddE += (long long)Power; // Energy(xx.xxx) = 1kW in a Hour
nEnergy=(unsigned int)(AddE/180000000);
if(nEnergy!=Energy){
Energy=nEnergy;
ADCON1bits.ADON = 0;
IEC0bits.ADIE = 0;
WriteEEPROM();
IEC0bits.ADIE = 1;
ADCON1bits.ADON = 1;
}
}
return;
}
//-------------------------- ADC10 ------------------------
void InitADC10(void)
{
ADPCFG = 0x003C; // RB0 and RB1 are Analog input
ADCON1 = 0x00EE; // Auto ends TSAMP and starts conversion, Unsigned integer conversions
ADCON2 = 0x0100; // S/H All CH0, CH1
ADCON3 = 0x0416; // ADCS = 010110 of 384.615nS = 1*TAD of 30MIP fs=50kHz
// TSAMC = 00100 = 4*TAD
// Sample = TSAMP(4*TAD)+TCONV(4*12*TAD)
ADCHS = 0x0001; // A0+ > CH1,A1+ > CH2,A2+ > CH3, A1+ > CH0, AN- > VREF-
// A1 - ADCBUF0 - I, A0 - ADCBUF1 - V
IFS0bits.ADIF = 0; // Clear ISR flag
IEC0bits.ADIE = 1; // Enable interrupts
ADCON1bits.ADON = 1; // turn ADC ON
return;
}
//-------------------------- LCD ------------------------
void lcd_init()
{
TRISE = 0;
lcd_command(0x33); // Command set format 4 bit
lcd_command(0x32); // Command set format 4 bit
lcd_command(0x28); // 2 line ,5*7 dot
lcd_command(0x0C); // Display ON , none curser
lcd_command(0x01); // Clear screen
}
void lcd_command(unsigned char com)
{
unsigned char buff; // For Keep command send to LCD
buff = (com & 0xF0)>>4; // Keep 4 bit high byte befor send to LCD
RS = 0; // Select send command to LCD
E = 1; // Start generate pluse clock LCD
LATE = (LATE & 0xFFF0)|buff; // Send data to LCD port
delay_ms(1);
E = 0; // Stop generate pluse clock LCD
delay_ms(1);
buff = (com & 0x0F); // Keep 4 bit low byte befor send to LCD
RS = 0; // Select send command to LCD
E = 1; // start generate pluse clock LCD
LATE = (LATE & 0xFFF0)|buff; // Send data to LCD port
delay_ms(1);
E = 0; // Stop generate pluse clock LCD
delay_ms(1);
}
void lcd_text(char text)
{
unsigned char buff; // For Keep data send to LCD
buff = (text & 0xF0)>>4; // Keep 4 bit high byte befor send to LCD
RS = 1; // Select send data to LCD
E = 1; // start generate pluse clock LCD
LATE = (LATE & 0xFFF0)|buff; // Send data to LCD port
delay_ms(1);
E = 0; // Stop generate pluse clock LCD
delay_ms(1);
buff = (text & 0x0F); // Keep 4 bit low byte befor send to LCD
RS = 1; // Write Command to LCD
E = 1; // start generate pluse clock LCD
LATE = (LATE & 0xFFF0)|buff; // Send data to LCD port
delay_ms(1);
E = 0; // Stop generate pluse clock LCD
delay_ms(1);
}
void lcd_puts(unsigned char addr,char *p)
{
lcd_command(0x02); // Set origin address of LCD
lcd_command(addr);
while(*p) // Check data pointer = 0?
{
lcd_text(*p);
p++;
}
}
void PrintLCD(unsigned char addr,long value)
{
int i;
char ibuff[7];
if(addr==0x83) {
value/=100;
ibuff[0] = (value/10000) | '0';
ibuff[1] = ((value000)/1000) | '0';
ibuff[2] = (((value000)00)/100) | '0';
ibuff[3] = ((((value000)00)0)/10) | '0';
ibuff[4] = '.';
ibuff[5] = ((((value000)00)0)) | '0';
ibuff[6] = 0;
if(ibuff[0]=='0') ibuff[0]=' ';
if((ibuff[1]=='0')&&
ibuff[0]==' ')) ibuff[1]=' ';
if((ibuff[2]=='0')&&
ibuff[1]==' ')) ibuff[2]=' ';
}else{
ibuff[0] = (value/10000) | '0';
ibuff[1] = ((value000)/1000) | '0';
ibuff[2] = '.';
ibuff[3] = (((value000)00)/100) | '0';
ibuff[4] = ((((value000)00)0)/10) | '0';
ibuff[5] = ((((value000)00)0)) | '0';
ibuff[6] = 0;
if(ibuff[0]=='0') ibuff[0]=' ';
}
lcd_puts(addr,&ibuff[0]);
}
//-------------------------- MISC ------------------------
void delay_ms(unsigned int ms) // Delay millisecond
{
unsigned int i,k;
for(i=0;i<ms;i++)
{
for(k=0;k<5120;k++); // Delay 1 ms each, at 7.3738 MHz at PLL 16x
}
}
//-------------------------- EEPROM Routine ------------------------
void eeprom_erase_word(unsigned long address_erase)
{
__asm__ volatile("MOV W1,NVMADRU"); // Keep High byte address
__asm__ volatile("MOV W0,NVMADR"); // Keep low byte address
__asm__ volatile("MOV #0x4044,W0"); // Load command
__asm__ volatile("MOV W0,NVMCON");
__asm__ volatile("DISI #5");
__asm__ volatile("MOV #0x55,W0"); // Lanch command step 1
__asm__ volatile("MOV W0,NVMKEY");
__asm__ volatile("MOV #0xAA,W1"); // Lanch command step 2
__asm__ volatile("MOV W1,NVMKEY");
NVMCONbits.WR = 1; // Start to write data to EEPROM
while(NVMCONbits.WR); // Wait until success
NVMCONbits.WREN = 0; // Clear WREN for ensure
}
void eeprom_write_word(unsigned long address,unsigned int val)
{
__asm__ volatile("MOV W1,TBLPAG"); // Keep High byte address
__asm__ volatile("TBLWTL W2,[W0]"); // Write data to table
__asm__ volatile("MOV #0x4104,W0"); // Load command
__asm__ volatile("MOV W0,NVMCON");
__asm__ volatile("DISI #5");
__asm__ volatile("MOV #0x55,W0"); // Lanch command step 1
__asm__ volatile("MOV W0,NVMKEY");
__asm__ volatile("MOV #0xAA,W1"); // Lanch command step 2
__asm__ volatile("MOV W1,NVMKEY");
NVMCONbits.WR = 1; // Start to write data to EEPROM
while(NVMCONbits.WR); // Wait until success
NVMCONbits.WREN = 0; // Clear WREN for ensure
}
unsigned int eeprom_read_word(unsigned long address)
{
__asm__ volatile("MOV W1,TBLPAG"); // Keep High byte address
__asm__ volatile("TBLRDL [W0],W4"); // Load data into W4
return(WREG4); // Return data for EEPROM
}
void WriteEEPROM(void)
{
unsigned int i,data;
eeprom_erase_word(CELL(iEEPROM));
eeprom_write_word(CELL(iEEPROM),0x0000);
delay_ms(1);
if(iEEPROM==511) iEEPROM=0;
else iEEPROM++;
eeprom_erase_word(CELL(iEEPROM));
eeprom_write_word(CELL(iEEPROM),Energy);
delay_ms(1);
}
void ResetEnergy(void)
{
unsigned int data,i,Pressed;
Pressed=0;
i=599;
lcd_puts(0x80,"Pressing at zero");
lcd_puts(0xC0,"to confirm: s.");
while(i<600){
lcd_command(0xCC);
lcd_text( (i/100) | '0' );
if(RESETSW==RESETSW_PRESSED) {
Pressed=1;
break;
}
delay_ms(6);
i--;
if(i==0) break;
}
if((Pressed)&&
(i/100)==0)) {
i=0;
while(i<512){
data=eeprom_read_word(CELL(i));
if(data!=0x0000) {
eeprom_erase_word(CELL(i));
eeprom_write_word(CELL(i),0x0000);
delay_ms(1);
}
else i++;
}
iEEPROM=511;
Energy=0;
AddE=0;
lcd_puts(0x80,"RESET Confirmed!");
lcd_puts(0xC0," ");
delay_ms(3000);
}else{
lcd_puts(0x80,"RESET Failed! ");
lcd_puts(0xC0," ");
delay_ms(3000);
}
lcd_puts(0x80,"P: Watts ");
lcd_puts(0xC0,"E: Units ");
}
void LoadEEPROM(void)
{
unsigned int i,data;
if(eeprom_read_word(CELL(511))==0xFFFF) {
for(i=0;i<512;i++) {
eeprom_erase_word(CELL(i));
eeprom_write_word(CELL(i),0x0000);
delay_ms(1);
}
iEEPROM=511;
Energy=0;
}else{
data=i=0;
while(i<512){
data=eeprom_read_word(CELL(i));
if(data!=0x0000) break;
else i++;
}
if(i>=512) iEEPROM=511;
else iEEPROM=i;
Energy=data; // in xx.xxx Resolution, maximum 65.535 Units
}
AddE=(long long)Energy*180000000; // 60*60*50*1000
}
//-------------------------- MAIN Routine ------------------------
int main(void)
{
int i;
TRISC |= 0x6000;
Samples = 0;
AccPwr=0;
Power=0;
LoadEEPROM();
lcd_init();
lcd_puts(0x80,"P: Watts ");
lcd_puts(0xC0,"E: Units ");
InitADC10(); // Start Sampling
for(;;)
{
PrintLCD(0x83,Power);
PrintLCD(0xC3,Energy);
if(RESETSW==RESETSW_PRESSED) {
ADCON1bits.ADON=0;
IEC0bits.ADIE=0;
ResetEnergy();
Samples=0;
AccPwr=0;
IEC0bits.ADIE=1;
ADCON1bits.ADON=1;
}
delay_ms(5);
}
return 0;
}
ใครใจดีช่วยแก้โค๊ด et-base dspic30f2010 การรับค่า ADC แสดงผล LCD ของ จาก W ให้แสดงออกมาเปน V หน่อยครับ
หรือใจดีเขียนให้ใหม่เลยจะขอบคุณมากครับ
ข้อมูล โปรแกรมควบคุม
#include <p30f2010.h>
#define RS LATEbits.LATE4
#define E LATEbits.LATE5
#define RESETSW PORTCbits.RC13
#define RESETSW_PRESSED 0
#define CELL(x) (0x7FFC00+2*(unsigned long)x) // Macro for access to EEPROM cell x(x = 0...511)
//-------------------------- Device Configuration ------------------------
_FOSC(CSW_FSCM_OFF & XT_PLL16);
_FWDT(WDT_OFF);
_FBORPOR(PBOR_ON & BORV_20 & PWRT_64 & MCLR_EN);
//-------------------------- Global Variables ------------------------
unsigned int Samples,Energy,iEEPROM;
long AccPwr,Power;
long long AddE;
//-------------------------- Interrupt Routine ------------------------
void __attribute__((__interrupt__)) _ADCInterrupt(void) // Fs = 50,000 Hz ( 1,000 Samples/Cycle of 50Hz )
{
long DCV,ACA;
unsigned int nEnergy;
IFS0bits.ADIF = 0; // Clear interrupt flag
DCV = (long)ADCBUF1;
ACA = (long)ADCBUF0-512; // AC Amp.
AccPwr += (DCV*ACA);
Samples++; // LSB = Least Significant Value per Bit
if(Samples==1000) { // Pwr(xx.xxx) = AccPwr * 1000 * (LSB of AccPwr) / 1000
Samples=0; // LSB of AccPwr = (LSB of V) * (LSB of A)
if(AccPwr<0) AccPwr=0;
Power=AccPwr/210; // LSB of V = Vpp / (2^n of ADC) = (50) / 1024
AccPwr=0; // LSB of A = App / (2^n of ADC) = (50+50) / 1024
// 210 ~ 209.7152 = 1 / ((50+/1024)*((50+50)/1024))
AddE += (long long)Power; // Energy(xx.xxx) = 1kW in a Hour
nEnergy=(unsigned int)(AddE/180000000);
if(nEnergy!=Energy){
Energy=nEnergy;
ADCON1bits.ADON = 0;
IEC0bits.ADIE = 0;
WriteEEPROM();
IEC0bits.ADIE = 1;
ADCON1bits.ADON = 1;
}
}
return;
}
//-------------------------- ADC10 ------------------------
void InitADC10(void)
{
ADPCFG = 0x003C; // RB0 and RB1 are Analog input
ADCON1 = 0x00EE; // Auto ends TSAMP and starts conversion, Unsigned integer conversions
ADCON2 = 0x0100; // S/H All CH0, CH1
ADCON3 = 0x0416; // ADCS = 010110 of 384.615nS = 1*TAD of 30MIP fs=50kHz
// TSAMC = 00100 = 4*TAD
// Sample = TSAMP(4*TAD)+TCONV(4*12*TAD)
ADCHS = 0x0001; // A0+ > CH1,A1+ > CH2,A2+ > CH3, A1+ > CH0, AN- > VREF-
// A1 - ADCBUF0 - I, A0 - ADCBUF1 - V
IFS0bits.ADIF = 0; // Clear ISR flag
IEC0bits.ADIE = 1; // Enable interrupts
ADCON1bits.ADON = 1; // turn ADC ON
return;
}
//-------------------------- LCD ------------------------
void lcd_init()
{
TRISE = 0;
lcd_command(0x33); // Command set format 4 bit
lcd_command(0x32); // Command set format 4 bit
lcd_command(0x28); // 2 line ,5*7 dot
lcd_command(0x0C); // Display ON , none curser
lcd_command(0x01); // Clear screen
}
void lcd_command(unsigned char com)
{
unsigned char buff; // For Keep command send to LCD
buff = (com & 0xF0)>>4; // Keep 4 bit high byte befor send to LCD
RS = 0; // Select send command to LCD
E = 1; // Start generate pluse clock LCD
LATE = (LATE & 0xFFF0)|buff; // Send data to LCD port
delay_ms(1);
E = 0; // Stop generate pluse clock LCD
delay_ms(1);
buff = (com & 0x0F); // Keep 4 bit low byte befor send to LCD
RS = 0; // Select send command to LCD
E = 1; // start generate pluse clock LCD
LATE = (LATE & 0xFFF0)|buff; // Send data to LCD port
delay_ms(1);
E = 0; // Stop generate pluse clock LCD
delay_ms(1);
}
void lcd_text(char text)
{
unsigned char buff; // For Keep data send to LCD
buff = (text & 0xF0)>>4; // Keep 4 bit high byte befor send to LCD
RS = 1; // Select send data to LCD
E = 1; // start generate pluse clock LCD
LATE = (LATE & 0xFFF0)|buff; // Send data to LCD port
delay_ms(1);
E = 0; // Stop generate pluse clock LCD
delay_ms(1);
buff = (text & 0x0F); // Keep 4 bit low byte befor send to LCD
RS = 1; // Write Command to LCD
E = 1; // start generate pluse clock LCD
LATE = (LATE & 0xFFF0)|buff; // Send data to LCD port
delay_ms(1);
E = 0; // Stop generate pluse clock LCD
delay_ms(1);
}
void lcd_puts(unsigned char addr,char *p)
{
lcd_command(0x02); // Set origin address of LCD
lcd_command(addr);
while(*p) // Check data pointer = 0?
{
lcd_text(*p);
p++;
}
}
void PrintLCD(unsigned char addr,long value)
{
int i;
char ibuff[7];
if(addr==0x83) {
value/=100;
ibuff[0] = (value/10000) | '0';
ibuff[1] = ((value000)/1000) | '0';
ibuff[2] = (((value000)00)/100) | '0';
ibuff[3] = ((((value000)00)0)/10) | '0';
ibuff[4] = '.';
ibuff[5] = ((((value000)00)0)) | '0';
ibuff[6] = 0;
if(ibuff[0]=='0') ibuff[0]=' ';
if((ibuff[1]=='0')&&ibuff[0]==' ')) ibuff[1]=' ';
if((ibuff[2]=='0')&&ibuff[1]==' ')) ibuff[2]=' ';
}else{
ibuff[0] = (value/10000) | '0';
ibuff[1] = ((value000)/1000) | '0';
ibuff[2] = '.';
ibuff[3] = (((value000)00)/100) | '0';
ibuff[4] = ((((value000)00)0)/10) | '0';
ibuff[5] = ((((value000)00)0)) | '0';
ibuff[6] = 0;
if(ibuff[0]=='0') ibuff[0]=' ';
}
lcd_puts(addr,&ibuff[0]);
}
//-------------------------- MISC ------------------------
void delay_ms(unsigned int ms) // Delay millisecond
{
unsigned int i,k;
for(i=0;i<ms;i++)
{
for(k=0;k<5120;k++); // Delay 1 ms each, at 7.3738 MHz at PLL 16x
}
}
//-------------------------- EEPROM Routine ------------------------
void eeprom_erase_word(unsigned long address_erase)
{
__asm__ volatile("MOV W1,NVMADRU"); // Keep High byte address
__asm__ volatile("MOV W0,NVMADR"); // Keep low byte address
__asm__ volatile("MOV #0x4044,W0"); // Load command
__asm__ volatile("MOV W0,NVMCON");
__asm__ volatile("DISI #5");
__asm__ volatile("MOV #0x55,W0"); // Lanch command step 1
__asm__ volatile("MOV W0,NVMKEY");
__asm__ volatile("MOV #0xAA,W1"); // Lanch command step 2
__asm__ volatile("MOV W1,NVMKEY");
NVMCONbits.WR = 1; // Start to write data to EEPROM
while(NVMCONbits.WR); // Wait until success
NVMCONbits.WREN = 0; // Clear WREN for ensure
}
void eeprom_write_word(unsigned long address,unsigned int val)
{
__asm__ volatile("MOV W1,TBLPAG"); // Keep High byte address
__asm__ volatile("TBLWTL W2,[W0]"); // Write data to table
__asm__ volatile("MOV #0x4104,W0"); // Load command
__asm__ volatile("MOV W0,NVMCON");
__asm__ volatile("DISI #5");
__asm__ volatile("MOV #0x55,W0"); // Lanch command step 1
__asm__ volatile("MOV W0,NVMKEY");
__asm__ volatile("MOV #0xAA,W1"); // Lanch command step 2
__asm__ volatile("MOV W1,NVMKEY");
NVMCONbits.WR = 1; // Start to write data to EEPROM
while(NVMCONbits.WR); // Wait until success
NVMCONbits.WREN = 0; // Clear WREN for ensure
}
unsigned int eeprom_read_word(unsigned long address)
{
__asm__ volatile("MOV W1,TBLPAG"); // Keep High byte address
__asm__ volatile("TBLRDL [W0],W4"); // Load data into W4
return(WREG4); // Return data for EEPROM
}
void WriteEEPROM(void)
{
unsigned int i,data;
eeprom_erase_word(CELL(iEEPROM));
eeprom_write_word(CELL(iEEPROM),0x0000);
delay_ms(1);
if(iEEPROM==511) iEEPROM=0;
else iEEPROM++;
eeprom_erase_word(CELL(iEEPROM));
eeprom_write_word(CELL(iEEPROM),Energy);
delay_ms(1);
}
void ResetEnergy(void)
{
unsigned int data,i,Pressed;
Pressed=0;
i=599;
lcd_puts(0x80,"Pressing at zero");
lcd_puts(0xC0,"to confirm: s.");
while(i<600){
lcd_command(0xCC);
lcd_text( (i/100) | '0' );
if(RESETSW==RESETSW_PRESSED) {
Pressed=1;
break;
}
delay_ms(6);
i--;
if(i==0) break;
}
if((Pressed)&&(i/100)==0)) {
i=0;
while(i<512){
data=eeprom_read_word(CELL(i));
if(data!=0x0000) {
eeprom_erase_word(CELL(i));
eeprom_write_word(CELL(i),0x0000);
delay_ms(1);
}
else i++;
}
iEEPROM=511;
Energy=0;
AddE=0;
lcd_puts(0x80,"RESET Confirmed!");
lcd_puts(0xC0," ");
delay_ms(3000);
}else{
lcd_puts(0x80,"RESET Failed! ");
lcd_puts(0xC0," ");
delay_ms(3000);
}
lcd_puts(0x80,"P: Watts ");
lcd_puts(0xC0,"E: Units ");
}
void LoadEEPROM(void)
{
unsigned int i,data;
if(eeprom_read_word(CELL(511))==0xFFFF) {
for(i=0;i<512;i++) {
eeprom_erase_word(CELL(i));
eeprom_write_word(CELL(i),0x0000);
delay_ms(1);
}
iEEPROM=511;
Energy=0;
}else{
data=i=0;
while(i<512){
data=eeprom_read_word(CELL(i));
if(data!=0x0000) break;
else i++;
}
if(i>=512) iEEPROM=511;
else iEEPROM=i;
Energy=data; // in xx.xxx Resolution, maximum 65.535 Units
}
AddE=(long long)Energy*180000000; // 60*60*50*1000
}
//-------------------------- MAIN Routine ------------------------
int main(void)
{
int i;
TRISC |= 0x6000;
Samples = 0;
AccPwr=0;
Power=0;
LoadEEPROM();
lcd_init();
lcd_puts(0x80,"P: Watts ");
lcd_puts(0xC0,"E: Units ");
InitADC10(); // Start Sampling
for(;;)
{
PrintLCD(0x83,Power);
PrintLCD(0xC3,Energy);
if(RESETSW==RESETSW_PRESSED) {
ADCON1bits.ADON=0;
IEC0bits.ADIE=0;
ResetEnergy();
Samples=0;
AccPwr=0;
IEC0bits.ADIE=1;
ADCON1bits.ADON=1;
}
delay_ms(5);
}
return 0;
}