Jump to content


  • Content Count

  • Joined

  • Last visited

Everything posted by DavidT

  1. my_init() needs RS to be low for instructions. I don't see this being set. Whats the state of RW? If that's not it then I would make a simpler version that initialises the display and prints just 1 character to a specified address. David.
  2. Glad it worked. I can't see a reason for the difference either. David.
  3. With the following code with a 16F690 I get 515 from two 1k5 resistors dividing 5.01v supply. The resistors yield 2.525v at their junction which should be an ADC value of 516. Spot on given a 1 step error rate. #include <system.h> //Settings/Target 16F690 //Core configuration option_regs: #pragma DATA _CONFIG, _FCMEN_OFF & _IESO_OFF & _BOR_ON & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSCIO void write_data() //Function to write to EEPROM flash memory { intcon.7 = 0; //Disable interrupts pir2.4 = 0; //EEIF: Clear this bit which gets set after each write eecon2 = 0x55; //Required before writing to memory eecon2 = 0xAA; //Required before writing to memory eecon1.1 = 1; //WR: Writes data eedata to address eeadr while(eecon1.1==1); //Wait for write to complete (becomes 0 when complete) eeadr++; //Increment the address by 1 for next write } void main() { //Initialise all ports porta=0; portb=0; portc=0; //Main port settings (1=Input 0=Output) trisa = 0; //All pins Output except... trisa.2 = 1; //RA2 (Pin17) AN2 trisb = 0; //All pins Output trisc = 0; //All pins Output //ADC port settings (1=Analog 0=Digital) ansel = 0; //All pins digital except... ansel.2 = 1; //RA2 (Pin17) AN2 anselh = 0; //Static EEPROM data logging settings eecon1.7 = 0; //EEPGD: Access data memory eecon1.3 = 0; //WRERR: clear on startup in case previously set eecon1.2 = 1; //WREN: enable writing to memory eeadr = 0; //Start address //Static ADC settings adcon1 = 0b1010000; //AD Conversion Clock Fosc/16 pie1.6 = 0; //ADC interrupts disabled adcon0 = 0b10001001; //Right justify, Vdd as ref, AN2 active, AD module enabled //Run ADC char i; //Declare variable for timer for(i=0; i<1; i++); //Delay for acquisition capacitor to charge pir1.6 = 0; //ADIF: Clear the ADC interrupt flag adcon0.1 = 1; //GO: Start ADC acquisition while(adcon0.1==1); //Wait for conversion to complete (becomes 0) //Store results eedata = adresh; //High register write_data(); //Write to EEPROM eedata = adresl; //Low register write_data(); //Write to EEPROM while(1); //Wait here } //end main
  4. I would log the values of key registers (eg: adcon0/1) and ADC conversion values in EEPROM next. I think you need to trap actual settings when the conversion is performed (read them via your programmer to check them). I have some EEPROM code on this link and other examples if you need it. Different chip but should be easy to convert: http://www.flyelectric.ukgateway.net/pic-temp2.htm David.
  5. The ADC bits are determined by the chip you are using. Perhaps let us know what that is. To vary input voltage for testing you are presumably using a different/dual supply. To remove one complexity may I suggest you tie your PIC's input to Vdd so it definitely has the same voltage. The result really should be 1023 (if 10bit) irrespective of the exact voltage. 0 when tied to ground. Without having checked your code fully, are you telling the PIC what Vref to use? (Vdd or external). David.
  6. What is your reference voltage, where are you deriving it from and how many bits is your ADC? With a 10bit ADC I would expect 1023 from 5v input and a 5v reference. David.
  7. I use program memory as a buffer for an SD card logger. When I first tried the BoostC commands with a 16F88 they did not work; this is either because I implemented it wrong or I now believe because they are not intended for that chip. So I wrote my own functions. I won't bother posting my code since the BoostC ones should work for you. You need to control addressing 'manually'. Ie: you need to know how large your program is and only write to 'higher' address locations. These are most easily determined by looking at what locations your program occupies via your programmer. The occupied space with have random hex in it and the empty space 3FFF or similar in each word location. As a simple test to confirm that you are interpreting your addresses correctly, write some unique data to an address when you program the PIC (where 0xDE0 is the target address and 0x1234 the unique data). 'Read' your PIC to check that it is in the expected location after writing: #pragma DATA 0xDE0, 0x1234 You need your own code to set a start address, to increment that as you write, and to control how it wraps (or stops writing) when the range you choose becomes full. The 16F88 needs data to be erased manually which I don't think the 16F87x series needs. Addresses are set in the eeadh and eeadr pair and data is read and written via the eedath and eedata pair. Because data is written in 4 word blocks, the 'first' must start at addresses ending in '00' (ie: 0b...00). The PIC uses the least significant 2 bits to control how it buffers the first 3 'writes' then physically writes all 4 when the address increments to '11' (0b...11). This means that if you program stops after 3 writes, they will not actually be written to ROM and those recordings will be lost forever. So you either need to capture more data than you need or add code to always complete multiples of 4 writes. Hope this helps, David.
  8. Rye, I assume you want your program to write data on the fly to program memory space? You can only do this if the device supports this feature. Microchip refer to this as 'self-write' or 'processor read/write access to program memory' or similar. I believe their 'Enhanced Flash' based devices support this. To prevent over-writes the chips I've used have a setting for some predefined ranges. Alternatively your program needs to control addressing carefully, and cater for it wrapping when it fills. Confirm that your chip supports this feature and I can let you have an example if you wish. I assume you know that writing to data memory (EEPROM) is slightly different and supported in more devices. David.
  9. Thank you. These have given me a few more options to consider. David.
  10. Hi, I want to time-stamp events that I am logging, ie: 'n' seconds after startup will do. Does it matter which timer I use? Ie: will using standard delay functions elsewhere in the program interfere? Thanks, David.
  11. Yes, this code is from the C posted and I have checked again that it is 3FFF after programming. It refuses to over-write those 32 words whether I have the 4 words written or not. However... I start writing data in step 3 at A00h. So I have moved my 'step 1' 32 word erase there. This time it does over-write it correctly. So I've then tried my 'step 2' 4 word write also starting at A00h (in that erased block) and again over-writing them with 'step 3' as before. The 32 word erased block still gets over-written correctly but the data in those 4 addresses becomes eroneous. So there must be some hardware checking and expectation that writes will occur in blocks that were last erased. This is a pity because I was trying to be an extra 32 word block 'ahead' of the writes to make wrapping easier to recognise. It's also clear that data over-written with different data becomes corrupted if not erased first. I need to be more careful with my test data! I think these findings were along the lines that you were trying to persuade me so thanks for your perseverance and help! David.
  12. Thanks, C has been enough of a challenge so I have not tried to work through the assembler before: http://www.flyelectric.ukgateway.net/sd_card.asm http://www.flyelectric.ukgateway.net/sd_card.lst
  13. I'm using the SourceBoost IDE. Which file will show what you ask?
  14. Thank you, I appreciate the suggestion but that is not the problem. The memory is erased when I program the Pic and I still get this problem on first write. I have also done hundreds of tests; I've seen no evidence of the hardware *requiring* an erase immediately before a write and it's not really possible to enforce because the block sizes are different. I accept that the data sheet says you *must* erase first and I do so in my 'real' program. In this example I have simply kept simplifying the code in an attempt to identify the cause of the sequence changing. The screen prints don't show on my PC so here is a link of a rom read after executing the program: http://www.flyelectric.ukgateway.net/rom_error.jpg David.
  15. Hi, I've written a program to write to program memory using a 16F88. I've got all the individual bits working well and have been having problems stringing it all together. So I've simplified it again to request help with my current problem. I've been having problems with erases seeming to interact in unexpected ways with writes. To prove the error, I try to perform the following sequence of events: 1. Erase a 32 word block at the end of program memory (from location FC0h) 2. Write 4 unique values (0-3) in the middle of the erased block (from FC8h) 3. Over-write everything from the beginning of my buffer (A00h) to the end of program memory (5FFh) I'm expecting the erased block and 4 numbers to not be visible because the data in step 3 should over-write it. What I'm getting is step 3 then 1 then 2 (the erased block and unique numbers 0-3 are visible in the middle of the sequence of numbers written in step 3. Hopefully this is evident to you in the attached screen shot. Any advice please? Thanks, David. #include <system.h> //Generic device include #pragma DATA 0x2007, 0b11111101010000 //Config1 #pragma DATA 0x2008, 0b00 //Config2 void rom_load(); //Mechanism for managing erases and writes to ROM void rom_write(); //Buffers and writes 4 words to ROM void rom_erase(); //Erases 32 words in ROM #define buzz portb.3 //RB3 (Pin9) Buzzer unsigned short f; //test unsigned short rom_data; //Generic variable for writing data to ROM via rom_load() unsigned short rom_addr; //Target address for accessing program memory unsigned short rom_addr_erase; //Start of address for erasing ROM //FUNCTIONS section =========================================================== void rom_erase() //Function to ERASE a 32 word block of program memory { intcon.7 = 0; //Disable all interrupts while writing to memory pir2.4 = 0; //EEIF: Clear this bit which gets set after each write eecon1.3 = 0; //WRERR: Clear error flag bit in case has been set eecon1.7 = 1; //EEPGD: Select program memory eecon1.4 = 1; //FREE: Set to erase 32bytes of program memory eecon1.2 = 1; //WREN: Enable erase/writes eecon2 = 0x55; //Required before writing to memory eecon2 = 0xAA; //Required before writing to memory eecon1.1 = 1; //WR: Initiates erase nop(); nop(); //nop instructions required eecon1.2 = 0; //WREN: Disable erase/writes eecon1.4 = 0; //FREE: Disable erase operation //intcon.7 = 1; //Enable interrupts again (if used) } //------------------------------------------------------------------------------ void rom_write() //Function to WRITE 4 words (8bytes) to program memory { intcon.7 = 0; //Disable all interrupts while writing to memory pir2.4 = 0; //EEIF: Clear this bit which gets set after each write eecon1.3 = 0; //WRERR: Clear error flag bit in case has been set eecon1.7 = 1; //EEPGD: Select program memory eecon1.4 = 0; //FREE: Enable writes instead of erase eecon1.2 = 1; //WREN: Enable erase/writes eecon2 = 0x55; //Required before writing to memory eecon2 = 0xAA; //Required before writing to memory eecon1.1 = 1; //WR: Initiates write (buffers first 3 words) nop(); nop(); //Two nop instructions required while(eecon1.1==1); //Wait for write to complete (becomes 0 when complete) eecon1.4 = 0; //FREE: Disable erase operation //intcon.7 = 1; //Enable interrupts again (if used) } //------------------------------------------------------------------------------ void rom_load() //Function to write single words to program memory { //Set address to write HIBYTE(eeadrh,rom_addr);//Put high 8 bits in 'proper' register LOBYTE(eeadr, rom_addr);//Low 8 bits //Write data to ROM (1st 3 words are buffered by PIC, all are written after 4th) HIBYTE(eedath,rom_data);//Put high 8 bits in 'proper' register LOBYTE(eedata,rom_data);//Low 8 bits rom_write(); //Write to ROM //Increment address rom_addr++; } //=========================================================================== void main() //main program { //Initialise all ports, etc porta=0; portb=0; //Start low //Oscillator config osccon.6 = 1; //4MHz osccon.5 = 1; osccon.4 = 0; //Main port settings (1=Input 0=Output) trisa = 0; trisb = 0; //ADC port settings (1=Analog 0=Digital) ansel = 0; //Erase first 32 words of ROM rom_addr_erase = 0xFC0; //Set start address HIBYTE(eeadrh,rom_addr_erase); //Put high 8 bits in 'proper' register LOBYTE(eeadr, rom_addr_erase); //Low 8 bits rom_erase(); //Erase 32 words rom_addr=0xFC8; //Write 4 words in section just erased for (f=0; f<4; f++) { rom_data=f; rom_load(); } //----------------------------------------------------------------------------- //Fill program memory rom_addr=0xA00; for (f=0; f<0x600; f++) { rom_data=f; rom_load(); } //Beep when complete buzz=1; delay_ms(10); buzz=0; //Wait here while(1); } //end main
  16. You are a star, thank you. Somebody must have wanted to torture us when they arranged those bits! It's working now with everything in the right place. #pragma DATA 0x2007, 0b11111101010000 #pragma DATA 0x2008, 0b00 I'm developing a logger to a microSD card; my first attempt at serial/external comms. Even that seems to be giving me a valid response to my first command; things are looking up David.
  17. I'm trying to set in the last bits: 1 Brownout enabled 0 MCLR is IO 0 Powerup enabled 0 Watchdog disabled 100 INTRC IO on both
  18. I've tried the following both with the 0x2007 and _CONFIG1 etc. Both compile without errors but PIC does not run. I'll try it on another PIC that I'm more familiar with tomorrow. #pragma DATA 0x2007, 0b11111101000100 #pragma DATA 0x2008, 0b00
  19. You are both right. Ettore your config statements have worked and Raghunathan I did need to configure osccon. For the record the following code is making two LEDs flash correctly: #include <system.h> #pragma DATA _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO #pragma DATA _CONFIG2, _IESO_OFF & _FCMEN_OFF void main() { porta=0; portb=0; trisa = 0; trisb = 0; ansel = 0; osccon.6 = 1; osccon.5 = 1; osccon.4 = 0; while(1) { porta.0=1; porta.7=1; delay_ms(250); delay_ms(250); porta.0=0; porta.7=0; delay_ms(250); delay_ms(250); } //end while } //end main Where did I dream up the __config part? Well here's an extract from the header file which I interpreted in correctly: Thanks for your help, David.
  20. Hi folk, I'm using a 16F88 for the first time and am struggling to get it working. I'm no expert but have used a number of other PICs successfully. I suspect my internal oscilator config because the data sheet refers to an INTOSC mode (8MHz) and INTRC (31kHz) but I only see an INTRC_IO option in the header file. I'm using the SourceBoost IDE and the target is set to the correct device. I've programmed the chip with 2 programmers. I've tried 2 new PICs. I have 8 LEDs and a buzzer connected to various ports. The RA6/OSC2/CLKO port is always high and sometimes RA0 for a while. Any comments please? As an aside, is there any way to set the config word with 0's and 1's rather than the 'text' approach? The text does not always seem to match the data sheets exactly. Thanks, David. #include <system.h> #pragma DATA __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO #pragma DATA __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF #pragma CLOCK_FREQ 4000000 void main() { porta=0; portb=0; trisa = 0; trisb = 0; ansel = 0; while(1) { porta=1; portb=1; delay_ms(250); porta=0; portb=0; delay_ms(250); } //end while } //end main
  21. Volatile is fine surely for the SD card buffer because it is only a temporary store before writing to the card. I accept this implies that it's OK to loose any data not written to the card when switching it off. I want to minimise external components and the complexity that goes with that. This pushes me towards the 18F range where I can easily get up to 1k EEPROM and over 3k RAM. So I will go this route probably using RAM for caching since it is so much easier and quicker. Thanks for helping me think the options through. David.
  22. Hi. I believe it's necessary to set both the 'tris' registers and 'ansel' to set up inputs and outputs correctly. Ansel seems to default to 1's (=analogue). For instance, try setting ansel.4=0; (RC0 digital). Also try simplifying your code in main() to set specific outputs high and low (eg: DS1=1;) and add your more complex logic once that's working. David.
  23. Yes, just considering caching options. I'd prefer to avoid a separate memory chip. Some 18F's come with 1024bytes EEPROM which would be perfect. A 16F with 368byte EEPROM + 144bytes as ordinary variables in RAM seems another option. Is data RAM is rated at 1million writes?
  24. SD/MMC cards need 512byte buffers and most 16F's only go to 256 in EEPROM, some 368. So yes, Pavel understood me correctly. I did mean program memory. Thanks for pointing out the flash_ statements. Will these will work with any 'self-write' PIC in the 16F and 18F ranges or only the ones mentioned? David.
  • Create New...