Jump to content

Flyer

EstablishedMember
  • Content Count

    13
  • Joined

  • Last visited

Community Reputation

0 Neutral

About Flyer

  • Rank
    Newbrie
  1. Dave Fairly trivial but took me ages to find. The eeprom_read gives an incorrect answer if there is still a write running. It needs the same test for write completion e.g while (eecon1.WR); as the eeprom_write before continuing. Obviously having found it, it can be done outside of the routine but would be better included Best Regards Peter
  2. Douglas Sorry I haven't replied to your other posts - I've been working on something else recently and not looking at this board. Glad you've got it all working and the code was useful. The library rebuild was just a generic to cover my likely future uses. Best Regards Peter
  3. Dave I'm trying to read a fast asynch datafeed that broadcasts 52 characters at 115200 baud (4.5msec) every 1/64th second (15msec). I don't need to capture every packet, two a second would be fine . It appears that unless I do all the processing on the incoming characters polled and with interrupts disabled I am losing characters. Certainly my simple approach of setting a semaphore in the receive ISR does not work even with the receive task set at top priority. Knowing the internals of Novo, can you offer any advice for an optimum approach Thanks Peter
  4. I've just spent a couple of days experimenting with Novo and am seriously impressed. This will simplify all my PIC projects. For example find attached some code for a PIC 16F88 to drive a servo based on the position of a potentiometer (0-5VDC) This uses 3 tasks: The first reads the ADC and waits on a semaphore set in the interrupt routine to signal completion of conversion The second cycles every 20msec to provide the basic timebase for the servo output, it uses the output of the ADC to set up timer1 as a oneshot which provides the variable length pulse, the pulse is turned off in the interrupt routine fired by the timer. The third just pulses an output as a heartbeat. At the same time the ADC routine outputs to an LCD display what its doing. The Novo environment appears completely robust, in particular, I'm impressed that the LCD routines work within the tasks and that the embedded second timer interrupt works perfectly. It did take some time to understand everything and get it all working - but a great investment in time for the future. Key facts: Don't forget the linker switches -swcs when you set up a new project using Novo Do use version 6.7 David, Pavel; Many congrats on a great product Best regards Peter /////////////////////////////////////////////// // Servo controller with LCD monitor /////////////////////////////////////////////// // Uses Novo RTOS // // // // Target Device: PIC16F88 20MHz // // Author: Peter Mather // // Version History: // V1.0 - 28/5/2007 #include <system.h> #include <novocfg_pic16t5e5ts1.h> #include <novo.h> #pragma CLOCK_FREQ 20000000 #pragma DATA _CONFIG, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF & _HS_OSC //#pragma DATA _CONFIG, _CP_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_OFF & _WDT_OFF & _HS_OSC #define LCD_ARGS 2, /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \ 1, /* Use busy signal: 1 = use busy, 0 = use time delays */\ PORTB, TRISB, /* Data port and data port tris register */ \ PORTB, TRISB, /* Control port and control port tris register */ \ 0, /* Bit number of control port is connected to RS */ \ 1, /* Bit number of control port is connected to RW */ \ 3 /* Bit number of control port is connected to Enable */ #include <lcd_driver.h> // include the LCD template code #define hTask0 0 #define hTask1 1 #define hTask2 2 #define hSemaphore 0 static unsigned short conversion, times; void interrupt( void ) { if( intcon.TMR0IF ) { // update system time every 1ms (actually is 204.8us x 5 = 1.024ms) static BYTE intDivider; if( ++intDivider == 5 ) { intDivider = 0; SysTimerUpdate(); } intcon.TMR0IF = 0; //clear TMR0 overflow flag } if(pir1.ADIF) { pir1.ADIF = 0; SysSignalSemaphoreIsr(hSemaphore); } if (pir1.TMR1IF) { t1con.TMR1ON =0; //turn off timer pir1.TMR1IF = 0;//reset flag porta.1 = 0;//turn off output } } void InitTimer() { // configure Timer0 option_reg.T0CS = 0; // use internal clock option_reg.PSA = 0; // use prescaler form timer 0 // so we get an interrupt around every 204.8us with 20MHz Clock // set prescaller to divide by 4 option_reg.PS0 = 1; option_reg.PS1 = 0; option_reg.PS2 = 0; // enable interrupts intcon.PEIE = 1; //enable peripheral interrupts pir1.ADIF = 0; //clear ADC flag pir1.TMR1IF=0; //clear timer 1 flag t1con=0; //set up timer1, system clock, no prescale, stopped intcon.TMR0IE = 1; //enable TMR0 overflow bit pie1.TMR1IE=1; // enable timer 1 overflow interrupt enable pie1.ADIE = 1; //enable ADC interrupt intcon.GIE = 1; //enable global interrupts } void Task0() { while( 1 ) { HIBYTE(tmr1h,times); //set timer duration LOBYTE(tmr1l,times); t1con.TMR1ON=1; //turn on timer porta.1 = 1; //set output on Sys_Sleep( 20 );//sleep for 20msec } } void Task1() { while(1) { clear_bit(pir1,ADIF); set_bit(adcon0,GO); //Start the conversion Sys_WaitSemaphore(hSemaphore, EVENT_NO_TIMEOUT); MAKESHORT(conversion,adresl,adresh); if(conversion<=12) conversion=0; else conversion=conversion-12; if(conversion>=1000) conversion=999; conversion=conversion * 5; lcd_gotoxy(0,0); times=55536+conversion; lprintf("Reading %6d",conversion); lcd_gotoxy(0,1); lprintf("Writing %6u",times); Sys_Sleep( 100 ); } } void Task2() { while( 1 ) { porta.2 = 0; // 500ms delay Sys_Sleep( 250 ); // can only sleep for a maximum of 255 with 8 bit timers Sys_Sleep( 250 ); porta.2 = 1; // 500ms delay Sys_Sleep( 250 ); Sys_Sleep( 250 ); } } void main() { ansel=1; trisa = 0x01; porta=0; lcd_setup(); lprintf("test"); InitTimer(); SysInit(); SysCreateTask( hTask0, 2, Task0 ); SysCreateTask( hTask1, 4, Task1 ); SysCreateTask( hTask2, 4, Task2 ); SysStartTask( hTask0 ); SysStartTask( hTask1 ); SysStartTask( hTask2 ); adcon0=0; set_bit(adcon1,ADCS2); set_bit(adcon0,ADCS1); clear_bit(adcon0,ADCS0); //set clock divide by 64; set_bit(adcon1,ADFM); // Scale 0-1023 clear_bit(adcon0,CHS0); clear_bit(adcon0,CHS1); clear_bit(adcon0,CHS2); //Set channel to 0; set_bit(adcon0,ADON); //turn on the A to D; InitTimer(); while( 1 ) { Sys_Yield(); } }
  5. OK I've got everthing working now, the update to 6.7 seemed to solve things Best Regards Peter
  6. As requested, using 16F88 with LCD connected to portB only 4 bit bit 0 - RS bit 2 - R/W bit 3 - E bits 4-7 data Works as below with LCD calls commented out, errors as above if enabled Best regards Peter [/////////////////////////////////////////////// // Independant LED flash /////////////////////////////////////////////// // Uses Novo RTOS // // This code flashes two LEDs at independant rates // using 2 task to do this. // // Target Device: PIC16F88 // // Author: David Hobday // // Version History: // V1.0 - 17/09/2006 // Initial release. #include <system.h> #define LCD_ARGS 2, /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \ 1, /* Use busy signal: 1 = use busy, 0 = use time delays */\ PORTB, TRISB, /* Data port and data port tris register */ \ PORTB, TRISB, /* Control port and control port tris register */ \ 0, /* Bit number of control port is connected to RS */ \ 2, /* Bit number of control port is connected to RW */ \ 3 /* Bit number of control port is connected to Enable */ #include <lcd_driver.h> // include the LCD template code #include <novocfg_pic16t3e5ts1.h> #include <novo.h> #pragma DATA _CONFIG, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF & _HS_OSC #pragma CLOCK_FREQ 20000000 #define hTask0 0 #define hTask1 1 #define DELAY delay_s( 2 ) #define DELAY_SHORT delay_ms( 100 ) void interrupt( void ) { // update system time every 1ms (actually is 204.8us x 5 = 1.024ms) static BYTE intDivider; if( ++intDivider == 5 ) { intDivider = 0; SysTimerUpdate(); } intcon.TMR0IF = 0; //clear TMR0 overflow flag } void InitTimer() { // configure Timer0 option_reg.T0CS = 0; // use internal clock option_reg.PSA = 0; // use prescaler form timer 0 // so we get an interrupt around every 204.8us with 20MHz Clock // set prescaller to divide by 4 option_reg.PS0 = 1; option_reg.PS1 = 0; option_reg.PS2 = 0; // enable interrupts intcon.TMR0IE = 1; //enable TMR0 overflow bit intcon.GIE = 1; } void Task0() { while( 1 ) { porta.2 = 0; Sys_Sleep( 100 ); porta.2 = 1; Sys_Sleep( 100 ); } } void Task1() { while( 1 ) { porta.1 = 0; // 500ms delay Sys_Sleep( 250 ); // can only sleep for a maximum of 255 with 8 bit timers Sys_Sleep( 250 ); porta.1 = 1; // 500ms delay Sys_Sleep( 250 ); Sys_Sleep( 250 ); } } void main() { ansel = 1; trisa = 0x01; trisb = 0x00; // lcd_setup(); InitTimer(); SysInit(); SysCreateTask( hTask0, 2, Task0 ); SysCreateTask( hTask1, 2, Task1 ); SysStartTask( hTask0 ); SysStartTask( hTask1 ); // lprintf("test"); while( 1 ) { Sys_Yield(); } }
  7. If you post an attachment that contains a simple sample project that demonstrates this issue it would help. Novo RTOS has been used with the standard LCD routines quick successfully. Regards Dave
  8. More info if the call to LCD_setup is after any call to SysCreateTask then a linker error Internal Error: Var not found id:0x10000E01:0x008:0x00000250 in Function 'LCD_Read' happens. The linker succeeds if the call is before SysCreateTask but then the program doesn't operate
  9. Has anyone run RTOS using the LCD routines? The demo routines run perfectly in both the IDE and in circuit, but as soon as I add in calls to the LCD everthing seems to stop. Thanks Peter
  10. Dave Thanks for that - solved Best Regards Peter
  11. Has anyone got a working code example under 6.21 for the 16F877A using the 10 bit ADC conected to the simulated voltage input source plugin. I can get it working with the real chip fine but can't get anywhere with the simulator which is slowing development. I suspect a bug in the simulator but can't prove it. Thanks Flyer
  12. Yod Set up a PWM frequency to cover the servo pulse length - say 400HZ. Then electronically AND the PWM output pin with another pin that you set positive in the PWM interrupt routine for one cycle every 8. This will give you the correct pulse length and repeat rate. You may be able to do it by setting the PWM pin to an input in the TRIS register for 7 cycles out of 8 but I haven't tried this - the other definitely works. Best regards Flyer
  13. Can I please request that the simulation of the ADC in this chip is considered for the next release. the 877 doesn't have the same registers (ANSEL) and the 88 is now such good value and so functional that it must be the chip of choice (ducks...) I note another user also suffering from this in the support forum Many Thanks Peter
×
×
  • Create New...