 |
 |
| View previous topic :: View next topic |
| Author |
Message |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Wed Jul 15, 2015 6:35 am |
|
|
Unfortunately the writing is not working by me. I've changed the initial zeros to 0,1,2,3 and I also read these back with RS232. Not the 5,6,7,8 which must be written to the HEF in the main.
| Code: | #include <16F1708.H>
#FUSES INTRC_IO,NOWDT
#FUSES NOPUT,NOMCLR,PROTECT,BROWNOUT,BORV25 //PUT voor 64ms delay bij opstarten en bij brown-out
#FUSES NOCLKOUT,NOIESO
#FUSES NOFCMEN,WRT, NOPPS1WAY
#FUSES NOSTVREN,NODEBUG,NOLVP
#Device ADC=8
#use delay(clock=8000000) //Fuses and delay are set, so int osc is set at 8Mhz.
#use rs232(baud=9600, xmit = PIN_A0) //UART1 is pin 5 en 6, UART2 is pin 12 en 13
//Register and bit definitions
#byte PMADRH=getenv("SFR:PMADRH")
#byte PMADRL=getenv("SFR:PMADRL")
#byte PMDATH=getenv("SFR:PMDATH")
#byte PMDATL=getenv("SFR:PMDATL")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit FREE=getenv("BIT:FREE")
#bit LWLO=getenv("BIT:LWLO")
#BIT WR=getenv("BIT:WR")
#byte PMCON2=getenv("SFR:PMCON2")
#define HEF 0xF80
void my_erase_program_eeprom(int16 address)
{
//erases the page at the selected address
disable_interrupts(GLOBAL);
CFGS=FALSE;
PMADRL=make8(address,0);
PMADRH=make8(address,1);
CFGS=FALSE;
FREE=TRUE;
WREN=TRUE;
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
WREN=FALSE;
enable_interrupts(GLOBAL);
}
void my_write_program_memory(int16 address, int16 *data, int8 ctr)
{
//Beware - this does not erase a page for you, and will not handle
//a write that goes beyond the end of a page. Only works to
//write ctr bytes, to the program memory starting at address
int8 count;
disable_interrupts(GLOBAL);
WREN=TRUE;
CFGS=FALSE;
LWLO=TRUE; //load latches only
PMADRL=make8(address,0);
PMADRH=make8(address,1);
for (count=0;count<((ctr/2)-1);count++)
{
PMDATL=make8(data[count],0);
PMDATH=make8(data[count],1);
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
PMADRL++;
}
LWLO=FALSE;
PMDATL=make8(data[count],0);
PMDATH=make8(data[count],1); //last word
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
WREN=FALSE;
enable_interrupts(GLOBAL);
}
//memory layout definitions
struct twobytes
{
int8 l;
int8 h;
};
union prog_mem
{
int16 word;
struct twobytes b;
};
#ROM int16 HEF={0,1,2,3} //ensures the compiler will not accidentally
//put something else here.
void main()
{
//output_high (PF_OK_OUT); // PF hoog maken zodat bij reset geen pf gegeven wordt.
setup_oscillator(OSC_8MHZ);
setup_dac(DAC_OFF);
setup_vref(VREF_OFF);
setup_adc_ports(sAN2|sAN4|sAN6|sAN9|sAN10|sAN11|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8); // Built-in A/D setup function TAD is 2µSec
//setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); // 32,8 ms tot overflow (0.125us*4*256*256)
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8|T1_GATE); // 4us per ophoging van timer1
setup_timer_2(T2_DIV_BY_1, 255, 1); // Setup for 8 bit at 4kHz
setup_timer_6(T6_disabled,250,1);
//enable_interrupts(GLOBAL);
//enable_interrupts(INT_TIMER4);
// voor bewaren standby status, opstarten
struct
{
union prog_mem I_cal;
union prog_mem I_0A;
union prog_mem I_16A;
union prog_mem komma_8;
} values;
values.I_cal.b.l = 5;
values.I_0A.b.l = 6;
values.I_16A.b.l = 7;
values.komma_8.b.l = 8; //so they are different
//erase the page
my_erase_program_eeprom(HEF);
//write the values
my_write_program_memory(HEF, &values, 8);
//and read them back - CCS read works fine
read_program_memory(HEF,&values,8);
while(1)
{
printf("%u ",values.I_0A.b.l);
printf("%u ",values.I_cal.b.l);
printf("%u ",values.I_16A.b.l);
printf("%u ",values.komma_8.b.l);
delay_cycles(1);
}
}
|
Do you have any idea?  |
|
 |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Tue Jul 28, 2015 3:04 am |
|
|
Today I'm looking again at the HEF program to make it work. I've discovered that the erase function Ttelmah made is not working for me, but it is like the datasheet tells us so I don't know why it isn't working.
| Code: |
#include <16F1708.H>
#FUSES INTRC_IO,NOWDT
#FUSES NOPUT,NOMCLR,PROTECT,BROWNOUT,BORV25 //PUT voor 64ms delay bij opstarten en bij brown-out
#FUSES NOCLKOUT,NOIESO
#FUSES NOFCMEN,WRT, NOPPS1WAY
#FUSES NOSTVREN,NODEBUG,NOLVP
#Device ADC=8
#use delay(clock=8000000) //Fuses and delay are set, so int osc is set at 8Mhz.
#use rs232(baud=9600, xmit = PIN_A0) //UART1 is pin 5 en 6, UART2 is pin 12 en 13
//Register and bit definitions
#byte PMADRH=getenv("SFR:PMADRH")
#byte PMADRL=getenv("SFR:PMADRL")
#byte PMDATH=getenv("SFR:PMDATH")
#byte PMDATL=getenv("SFR:PMDATL")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit FREE=getenv("BIT:FREE")
#bit LWLO=getenv("BIT:LWLO")
#BIT WR=getenv("BIT:WR")
#byte PMCON2=getenv("SFR:PMCON2")
#define HEF 0xF80
int i = 0;
void my_erase_program_eeprom(int16 address)
{
//erases the page at the selected address
disable_interrupts(GLOBAL);
CFGS=FALSE;
PMADRL=make8(address,0);
PMADRH=make8(address,1);
CFGS=FALSE;
FREE=TRUE;
WREN=TRUE;
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
WREN=FALSE;
enable_interrupts(GLOBAL);
}
void my_write_program_memory(int16 address, int16 *data, int8 ctr)
{
//Beware - this does not erase a page for you, and will not handle
//a write that goes beyond the end of a page. Only works to
//write ctr bytes, to the program memory starting at address
int8 count;
disable_interrupts(GLOBAL);
WREN=TRUE;
CFGS=FALSE;
LWLO=TRUE; //load latches only
PMADRL=make8(address,0);
PMADRH=make8(address,1);
for (count=0;count<((ctr/2)-1);count++)
{
PMDATL=make8(data[count],0);
PMDATH=make8(data[count],1);
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
PMADRL++;
}
LWLO=FALSE;
PMDATL=make8(data[count],0);
PMDATH=make8(data[count],1); //last word
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
WREN=FALSE;
enable_interrupts(GLOBAL);
}
//memory layout definitions
struct twobytes
{
int8 l;
int8 h;
};
union prog_mem
{
int16 word;
struct twobytes b;
};
#ROM int16 HEF={10,11,12,13} //ensures the compiler will not accidentally
//put something else here.
void main()
{
//output_high (PF_OK_OUT); // PF hoog maken zodat bij reset geen pf gegeven wordt.
setup_oscillator(OSC_8MHZ);
setup_dac(DAC_OFF);
setup_vref(VREF_OFF);
setup_adc_ports(sAN2|sAN4|sAN6|sAN9|sAN10|sAN11|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8); // Built-in A/D setup function TAD is 2µSec
//setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); // 32,8 ms tot overflow (0.125us*4*256*256)
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8|T1_GATE); // 4us per ophoging van timer1
setup_timer_2(T2_DIV_BY_1, 255, 1); // Setup for 8 bit at 4kHz
setup_timer_6(T6_disabled,250,1);
//enable_interrupts(GLOBAL);
//enable_interrupts(INT_TIMER4);
// voor bewaren standby status, opstarten
struct
{
union prog_mem I_cal;
union prog_mem I_0A;
union prog_mem I_16A;
union prog_mem komma_8;
} values;
values.I_cal.b.l = 5;
values.I_0A.b.l = 6;
values.I_16A.b.l = 7;
values.komma_8.b.l = 8; //so they are different
//erase the page
//my_erase_program_eeprom(HEF);
//write the values
//my_write_program_memory(HEF, &values, 8);
//and read them back - CCS read works fine
read_program_memory(HEF,&values,8);
while(1)
{
printf("%u ",values.I_0A.b.l);
printf("%u ",values.I_cal.b.l);
printf("%u ",values.I_16A.b.l);
printf("%u ",values.komma_8.b.l);
printf("\n");
i++;
if(i >= 10)
{
my_erase_program_eeprom(HEF);
read_program_memory(HEF,&values,8);
}
if(i >= 20)
{
while(1);
}
delay_cycles(1);
}
}
|
Maybe another bug in version 5.026 so the code of Ttelmah isn't working for me (and probably is working for him)?? |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20061
|
|
Posted: Tue Jul 28, 2015 3:34 am |
|
|
You've probably killed the memory.
Seriously as soon as you put the erase function into a loop, this becomes likely.
The erase is going to be called every time i>=10.
The printf's take about 17mSec the erase 2mSec, the write 2mSec, so the total loop, about 20mSec. That will destroy the memory in about 1000 seconds, and that assumes the memory is new. Given yours has probably been used a large number of times already, much earlier death is likely.
'High endurance' is relative to the flash memory. It does not mean it can be written at all often. A simple loop erase, without the prints, can kill the memory in about 3 minutes..... |
|
 |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Tue Jul 28, 2015 5:02 am |
|
|
I still read the 10, 11 ,12 and 13 from the HEF.
The complete program also stops when I>20, because of the while(1). |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20061
|
|
Posted: Tue Jul 28, 2015 5:08 am |
|
|
OK.
At least you now tell us what you are seeing. It's still potentially using up life cycles, like they are out of date though...
The most likely thing is that one of the register or bit addresses is wrong in the compiler's database. Enter them manually from the data sheet. |
|
 |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Tue Jul 28, 2015 6:03 am |
|
|
I also tried to manually enter them, but that's also not working. Very strange.
| Code: |
//Register and bit definitions
//#byte PMADRH=getenv("SFR:PMADRH")
//#byte PMADRL=getenv("SFR:PMADRL")
#byte PMADRH=192
#byte PMADRL=191
//#byte PMDATH=getenv("SFR:PMDATH")
#byte PMDATH=194
//#byte PMDATL=getenv("SFR:PMDATL")
#byte PMDATL=193
//#bit CFGS=getenv("BIT:CFGS")
#bit CFGS=195.6
//#bit WREN=getenv("BIT:WREN")
#bit WREN=195.2
//#bit FREE=getenv("BIT:FREE")
#bit FREE=195.4
//#bit LWLO=getenv("BIT:LWLO")
#bit LWLO=195.5
//#BIT WR=getenv("BIT:WR")
#BIT WR=195.1
//#byte PMCON2=getenv("SFR:PMCON2")
#byte PMCON2=196
|
I also can try to add the ASM code from the datasheet in my program, maybe that will work. I will try something... |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20061
|
|
Posted: Tue Jul 28, 2015 7:14 am |
|
|
Seriously. I have just loaded 5.026 from a backup. Compiled my code as posted, with just fuses/clock/RS232 added.
Loaded the values with:
#ROM int16 0xF80 = {0,0,0,0}
Then ran this:
| Code: |
values.I_cal.b.l = 100;
values.I_0A.b.l = 101;
values.I_16A.b.l = 102;
values.komma_B.b.l = 103; //so they are different
my_erase_program_eeprom(0xF80);
my_write_program_memory(0x0F80, &values, 8);
read_program_memory(0x0F80,&values,8);
printf("%u ",values.I_0A.b.l);
printf("%u ",values.I_cal.b.l);
printf("%u ",values.I_16A.b.l);
printf("%u ",values.komma_B.b.l);
//Now clear again
my_erase_program_eeprom(0xF80);
read_program_memory(0x0F80,&values,8);
printf("%u ",values.I_0A.b.l);
printf("%u ",values.I_cal.b.l);
printf("%u ",values.I_16A.b.l);
printf("%u \n",values.komma_B.b.l);
//and read.
|
and it merrily displays:
101 100 102 103 255 255 255 255
Exactly as it should (erased cell is all 1's).
The code as posted works with your compiler.
Are you sure your PSU is good/stable?. Quite a few of the close chip relatives of this one, will not erase below a voltage quite a bit above the figure in the data sheet, if there is even a little noise on the supply line. There is a pulse in current during the erase (about 5mA), and unless regulation is very good, this can result in it failing. |
|
 |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Wed Jul 29, 2015 1:26 am |
|
|
Hmmm...very strange. If I compile this code with my fuses:
| Code: |
#include <16F1708.H>
#FUSES INTRC_IO,NOWDT
#FUSES NOPUT,NOMCLR,NOPROTECT,BROWNOUT,BORV25 //PUT voor 64ms delay bij opstarten en bij brown-out
#FUSES NOCLKOUT,NOIESO
#FUSES NOFCMEN,WRT, NOPPS1WAY
#FUSES NOSTVREN,NODEBUG,NOLVP
#Device ADC=8
#use delay(clock=8000000)
#use rs232(baud=9600, xmit = PIN_A0)
//Register and bit definitions
#byte PMADRH=getenv("SFR:PMADRH")
#byte PMADRL=getenv("SFR:PMADRL")
#byte PMDATH=getenv("SFR:PMDATH")
#byte PMDATL=getenv("SFR:PMDATL")
#bit CFGS=getenv("BIT:CFGS")
#bit WREN=getenv("BIT:WREN")
#bit FREE=getenv("BIT:FREE")
#bit LWLO=getenv("BIT:LWLO")
#BIT WR=getenv("BIT:WR")
#byte PMCON2=getenv("SFR:PMCON2")
#define HEF 0xF80
void my_erase_program_eeprom(int16 address)
{
//erases the page at the selected address
disable_interrupts(GLOBAL);
CFGS=FALSE;
PMADRL=make8(address,0);
PMADRH=make8(address,1);
CFGS=FALSE;
FREE=TRUE;
WREN=TRUE;
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
WREN=FALSE;
enable_interrupts(GLOBAL);
}
void my_write_program_memory(int16 address, int16 *data, int8 ctr)
{
//Beware - this does not erase a page for you, and will not handle
//a write that goes beyond the end of a page. Only works to
//write ctr bytes, to the program memory starting at address
int8 count;
disable_interrupts(GLOBAL);
WREN=TRUE;
CFGS=FALSE;
LWLO=TRUE; //load latches only
PMADRL=make8(address,0);
PMADRH=make8(address,1);
for (count=0;count<((ctr/2)-1);count++)
{
PMDATL=make8(data[count],0);
PMDATH=make8(data[count],1);
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
PMADRL++;
}
LWLO=FALSE;
PMDATL=make8(data[count],0);
PMDATH=make8(data[count],1); //last word
PMCON2=0x55;
PMCON2=0xAA;
WR=TRUE;
delay_cycles(1);
delay_cycles(1);
WREN=FALSE;
enable_interrupts(GLOBAL);
}
//memory layout definitions
struct twobytes
{
int8 l;
int8 h;
};
union prog_mem
{
int16 word;
struct twobytes b;
};
#ROM int16 0xF80 = {0,0,0,0}
void main()
{
struct
{
union prog_mem I_cal;
union prog_mem I_0A;
union prog_mem I_16A;
union prog_mem komma_B;
} values;
values.I_cal.b.l = 100;
values.I_0A.b.l = 101;
values.I_16A.b.l = 102;
values.komma_B.b.l = 103; //so they are different
my_erase_program_eeprom(0xF80);
my_write_program_memory(0x0F80, &values, 8);
read_program_memory(0x0F80,&values,8);
printf("%u ",values.I_0A.b.l);
printf("%u ",values.I_cal.b.l);
printf("%u ",values.I_16A.b.l);
printf("%u ",values.komma_B.b.l);
//Now clear again
my_erase_program_eeprom(0xF80);
read_program_memory(0x0F80,&values,8);
printf("%u ",values.I_0A.b.l);
printf("%u ",values.I_cal.b.l);
printf("%u ",values.I_16A.b.l);
printf("%u \n",values.komma_B.b.l);
//and read.
} |
I receive 0,0,0,0,0,0,0,0 in my RS232 hyperterminal like program.
So the write function is also not working. Is it possible that my fuses cause this problem, I already changed the PROTECT fuse to NOPROTECT but I also saw in the datasheet that this fuse should not affect the HEF. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20061
|
|
Posted: Wed Jul 29, 2015 2:32 am |
|
|
| What is your supply voltage, and the nature of your supply?. What smoothing is right by the chip?. |
|
 |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Wed Jul 29, 2015 3:09 am |
|
|
| 5V is coming from a stabilized power supply (a standard 30V/30V/5V), at the micro there is a 100nF capacitor nearby and a 470uF elco within a few centimeters/inches. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20061
|
|
Posted: Wed Jul 29, 2015 3:49 am |
|
|
WRT
Program memory write protected......
I was worried about voltage, since you have Brownout set at 2.5v, which suggests you are working down near this sort of voltage. |
|
 |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Wed Jul 29, 2015 4:44 am |
|
|
Yes that was the solution:
101 100 102 103 255 255 255 255
Thank you for your effort. |
|
 |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Mon Aug 31, 2015 3:49 am |
|
|
Now I'm trying to do more with the HEF there are two questions rised from the program Ttelmah wrote.
wherefore is the .b.l behind the variables? (L from lower byte from struct "twobytes"??)
I've added a 4th variable to the HEF but that's not working, are there 2 bytes reserved per variable so this function is too small:
my_write_program_memory(0x0F80, &values, 8);
If that's the case I need to write 10 instead of the 8 which is declared now. Is that correct? |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20061
|
|
Posted: Mon Aug 31, 2015 8:18 am |
|
|
Get a C textbook.....
This will tell you how structures and unions work.
The point is that the actual program memory, is 14bits wide, addressed as if it was 16bits wide (you write two bytes for every word in the memory), but only the low 8bits of each HEF location is 'high endurance'. So the data has to be written to the low eight bits of each 14 bits. The data layout allows you to address the low byte of each 14bit instruction.
Yes you have to expand your write for however many variables you have. Presumably you mean a 5th variable, since it already writes 4... |
|
 |
mvanvliet
Joined: 02 Jun 2009 Posts: 123 Location: The Netherlands
|
|
Posted: Mon Aug 31, 2015 8:46 am |
|
|
| Thank you for your reply. I indeed added a 5th variable. |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|