Hello,
I'm trying to command two servomotors using the compare module. (Pic 16f877)
1) I start counting the Timer1 at a minimum value.
2) Then I turn the pins (RB3 and RB4 but it doesn't matter) to 1.
3) I configure the CCP1L and CCP1H with a value bigger than the minimum value of the Tmr1 (to get 1 ms)
4) An interrupt occured and I turn off the pins RB3 and Rb4
4) The tmr1 continues counting until the overflow wich also creates an interrutp and re-turns on the pins
And so on..
With a single one servo, it work great. But When I connect the two servomotors, ther is a little conflict when the value of the two CCP1H/L and CCP2H/L are closed.
I think the fact that interrupts are generated during a very small time generates conflicts.
Am I right ?
Conflicts with interrupts
- janko.kaljevic
- Posts: 3565
- Joined: 16 Jun 2011 13:48
Re: Conflicts with interrupts
Hello,
Please can you explain this issue in more details.
I am afraid that I have not understood you well.
Best regard.
Please can you explain this issue in more details.
I am afraid that I have not understood you well.
Best regard.
Re: Conflicts with interrupts
I'm going to rephrase it,
I'm using the SPI protocol with the ENC28J60. At the same time I want to control two servomotors using the two CCP module (compare).
It works but I find some bugs (the servos change their position sometime without asking anything..).
Then I found out that the pin RC1 (CCP2) is also used by the SPI function (I configured it on PORTC as it was in the example), so maybe it's because of that despite that the outputs used to control the servos are on the PORTB..
I tried to change the PORTC in PORTD in the function SPI_INIT, but it didn't work at all..
Here is my code :
Thank you in advance
I'm using the SPI protocol with the ENC28J60. At the same time I want to control two servomotors using the two CCP module (compare).
It works but I find some bugs (the servos change their position sometime without asking anything..).
Then I found out that the pin RC1 (CCP2) is also used by the SPI function (I configured it on PORTC as it was in the example), so maybe it's because of that despite that the outputs used to control the servos are on the PORTB..
I tried to change the PORTC in PORTD in the function SPI_INIT, but it didn't work at all..
Here is my code :
Code: Select all
/*
* Project Name:
httpserver_example (Ethernet Library http server demo for ENC28J60 mcu)
* Target Platform:
PIC
* Copyright:
(c) mikroElektronika, 2006.
*
* description :
* this code shows how to use the ENC28J60 mini library :
* the board will reply to ARP & ICMP echo requests
* the board will reply to HTTP requests on port 80, GET method with pathnames :
* / will return the HTML main page
* /s will return board status as text string
* /t0 ... /t7 will toggle RC0 to RC7 bit and return HTML main page
* all other requests return also HTML main page
*
* target devices :
* any PIC with integrated SPI and more than 4 Kb ROM memory
* 32 to 40 MHz clock is recommended to get from 8 to 10 Mhz SPI clock,
* otherwise PIC should be clocked by ENC clock output due to ENC silicon bug in SPI hardware
* if you try lower PIC clock speed, don't be surprised if the board hang or miss some requests !
* tested with PIC16F877A@10Mhz on EasyPIC4 board
*
* EP settings :
* RA2 & RA3 pots jumper : closed
* PORTB : pull-down
* PORTC : pull-down
* BUTTONS : pull-up
*
* RC0 : !RESET to ENC reset input pin
* RC1 : !CS to ENC chip select input pin
* the ENC28J60 SPI bus CLK, SO, SI must be connected to the corresponding SPI pins of the PIC
* the INT and WOL signals from the ENC are not used
*
* Test configuration:
MCU: PIC16F877A
Dev.Board: EasyPIC4
Oscillator: HS, 10.000MHz
Ext. Modules: mE Serial Ethernet board
SW: mikroC v6.2.0.0.
* NOTES:
None.
*/
#define SPI_Ethernet_HALFDUPLEX 0
#define SPI_Ethernet_FULLDUPLEX 1
/************************************************************
* ROM constant strings
*/
const unsigned char httpHeader[] = "HTTP/1.1 200 OK\nContent-type: " ; // HTTP header
const unsigned char httpMimeTypeHTML[] = "text/html\n\n" ; // HTML MIME type
const unsigned char httpMimeTypeScript[] = "text/plain\n\n" ; // TEXT MIME type
unsigned char httpMethod[] = "GET /";
// supported http method
int compteur = 0;
int impulsionServoV = 56254; //position neutre du servomoteur vertical = 1,4ms
int impulsionServoH = 56233; //position neutre du servomoteur horizontal= 1,4ms
//butées gauche = 1ms = 56 035 - butée droite = 2ms = 56 535
/*
* web page, splited into 2 parts :
* when coming short of ROM, fragmented data is handled more efficiently by linker
*
* this HTML page calls the boards to get its status, and builds itself with javascript
*/
const char *indexPage = "<HTML><HEAD></HEAD><BODY>\
<h1 id=\"fileContent\">PIC + ENC28J60 Mini Web Server !!</h1>\
<a href=/>Reload</a>\
<script src=/s></script>\
<p id=\"keyCode\"></p>\
<table><tr><td valign=top><table border=1 style=\"font-size:20px ;font-family: terminal ;\">\
<tr><th colspan=2>ADC</th></tr>\
<tr><td>AN2</td><td><script>document.write(AN2)</script></td></tr>\
<tr><td>AN3</td><td><script>document.write(AN3)</script></td></tr>\
</table></td><td><table border=1 style=\"font-size:20px ;font-family: terminal ;\">\
<tr><th colspan=2>PORTB</th></tr>\
<script>\
var str,i;\
str=\"\";\
for(i=0;i<8;i++)\
{str+=\"<tr><td bgcolor=pink>BUTTON #\"+i+\"</td>\";\
if(PORTB&(1<<i)){str+=\"<td bgcolor=red>ON\";}\
else {str+=\"<td bgcolor=#cccccc>OFF\";}\
str+=\"</td></tr>\";}\
document.write(str) ;\
</script>\
" ;
const char *indexPage2 = "</table></td><td>\
<table border=1 style=\"font-size:20px ;font-family: terminal ;\">\
<tr><th colspan=3>PORTD</th></tr>\
<script>\
var str,i;\
str=\"\";\
for(i=0;i<8;i++)\
{str+=\"<tr><td bgcolor=yellow>LED #\"+i+\"</td>\";\
if(PORTD&(1<<i)){str+=\"<td bgcolor=red>ON\";}\
else {str+=\"<td bgcolor=#cccccc>OFF\";}\
str+=\"</td><td><a href=/t\"+i+\">Toggle</a></td></tr>\";}\
document.write(str) ;\
</script>\
</table></td></tr></table>\
This is HTTP request #<script>document.write(REQ)</script></BODY></HTML>\
" ;
/***********************************
* RAM variables
*/
unsigned char myMacAddr[6] = {0x00, 0x14, 0xA5, 0x76, 0x19, 0x3f} ; // MAC address
unsigned char myIpAddr[4] = {172, 17, 123, 50} ; // IP address
unsigned char getRequest[15] ; // HTTP request buffer
unsigned char dyna[31] ; // buffer for dynamic response
unsigned long httpCounter = 0 ; // counter of HTTP requests
/*******************************************
* functions
*/
/*
* put the constant string pointed to by s to the ENC transmit buffer
*/
unsigned int putConstString(const char *s)
{
unsigned int ctr = 0 ;
while(*s)
{
SPI_Ethernet_putByte(*s++) ;
ctr++ ;
}
return(ctr) ;
}
/*
* put the string pointed to by s to the ENC transmit buffer
*/
unsigned int putString(char *s)
{
unsigned int ctr = 0 ;
while(*s)
{
SPI_Ethernet_putByte(*s++) ;
ctr++ ;
}
return(ctr) ;
}
void interrupt ()
{
if (PIR1.CCP1IF == 1)
{
PORTB.F1 = 0;
PIR1.CCP1IF = 0;
}
if (PIR2.CCP2IF == 1)
{
PORTB.F0 = 0;
PIR2.CCP2IF = 0;
}
if (PIR1.TMR1IF == 1)
{
PORTB.F1 = 1;
PORTB.F0 = 1;
PIR1.TMR1IF = 0;
TMR1L = 0xEF;
TMR1H = 0xD8;
/* initialisation du TMR1 à 55 535 */
}
}
/*
* this function is called by the library
* the user accesses to the HTTP request by successive calls to SPI_Ethernet_getByte()
* the user puts data in the transmit buffer by successive calls to SPI_Ethernet_putByte()
* the function must return the length in bytes of the HTTP reply, or 0 if nothing to transmit
*
* if you don't need to reply to HTTP requests,
* just define this function with a return(0) as single statement
*
*/
unsigned int SPI_Ethernet_UserTCP(unsigned char *remoteHost, unsigned int remotePort, unsigned int localPort, unsigned int reqLength)
{
unsigned int len = 0 ; // my reply length
unsigned int i ; // general purpose integer
if(localPort != 80) // I listen only to web request on port 80
{
return(0) ;
}
// get 10 first bytes only of the request, the rest does not matter here
for(i = 0 ; i < 10 ; i++)
{
getRequest[i] = SPI_Ethernet_getByte() ;
}
getRequest[i] = 0 ;
if(memcmp(getRequest, httpMethod, 5)) // only GET method is supported here
{
return(0) ;
}
httpCounter++ ; // one more request done
if(getRequest[5] == 'h') // if request path is incrdibly equal to 9
{
if(impulsionServoV < 56405) //butée haute
{
impulsionServoV++;
//impulsionServoV = impulsionServoV+7;
CCPR1L = impulsionServoV;
CCPR1H = impulsionServoV>>8; // on place les 8 derniers bits dans le registre HIGHT du CCPR1
}
}
if(getRequest[5] == 'b') // if request path is incrdibly equal to 9
{
if(impulsionServoV > 56085) //butée basse
{
impulsionServoV--;
//impulsionServoV = impulsionServoV-7;
CCPR1L = impulsionServoV;
CCPR1H = impulsionServoV>>8; // on place les 8 derniers bits dans le registre HIGHT du CCPR1
}
}
if(getRequest[5] == 'g') // if request path is incrdibly equal to 9
{
if(impulsionServoH > 56085)
{
impulsionServoH++;
//impulsionServoH = impulsionServoH+7;
CCPR2L = impulsionServoH;
CCPR2H = impulsionServoH>>8; // on place les 8 derniers bits dans le registre HIGHT du CCPR1
}
}
if(getRequest[5] == 'd') // if request path is incrdibly equal to 9
{
if(impulsionServoH < 56485)
{
impulsionServoH--;
//impulsionServoH = impulsionServoH-7;
CCPR2L = impulsionServoH;
CCPR2H = impulsionServoH>>8; // on place les 8 derniers bits dans le registre HIGHT du CCPR1
}
}
if(getRequest[5] == 'n') // if request path is incrdibly equal to 9
{
impulsionServoH = 56233;
impulsionServoV = 56254;
CCPR2L = impulsionServoH;
CCPR2H = impulsionServoH>>8; // on place les 8 derniers bits dans le registre HIGHT du CCPR1
CCPR1L = impulsionServoV;
CCPR1H = impulsionServoV>>8;
}
if(len == 0) // what do to by default
{
len = putConstString(httpHeader) ; // HTTP header
len += putConstString(httpMimeTypeHTML) ; // with HTML MIME type
len += putConstString(indexPage) ; // HTML page first part
len += putConstString(indexPage2) ; // HTML page second part
}
return(len) ; // return to the library with the number of bytes to transmit
}
/*
* this function is called by the library
* the user accesses to the UDP request by successive calls to SPI_Ethernet_getByte()
* the user puts data in the transmit buffer by successive calls to SPI_Ethernet_putByte()
* the function must return the length in bytes of the UDP reply, or 0 if nothing to transmit
*
* if you don't need to reply to UDP requests,
* just define this function with a return(0) as single statement
*
*/
unsigned int SPI_Ethernet_UserUDP(unsigned char *remoteHost, unsigned int remotePort, unsigned int destPort, unsigned int reqLength)
{
return 0 ; // back to the library with the length of the UDP reply
}
/*
* main entry
*/
void main()
{
CCP1CON = 0b00001010;
/* mode compare, bits 7 à 4 non utilisés,
bits 3 à 0 = génération d'une interruption et flag CCP1IF = 1 à l'égalité */
CCP2CON = 0b00001010;
// set PORTA as input for ADC
TRISB = 0b00000000;
// set PORTB as input for buttons
INTCON = 0b11000000;
/* GIE = 1 : autoriser toutes les interruptions
PEIE = 1 : autoriser les interruptions causées par les périphériques
bits 5 à 0 non utilisés */
T1CON = 0b00100001;
/* bits 7-6 non implémentés
bit 5-4 = 10 : prédiviseur de 4
bits 3-1 = 000 : utilisation d'un quartz externe et mode timer activé
bit 0 = 1 : timer1 activé */
PIE1 = 0b00000101;
/* bits 7-3 et 1 à 0 : non utilisés
bit 2 (CCP1IE)= 1 : autorisation des interruptions de CCP1
bit 0 = 1 : autorise iterruption débordement TMR1 */
PIE2 = 0b00000001;
/* bits 7-1: non utilisés
bit 0 (CCP2IE)= 1 : autorisation des interruptions de CCP2*/
TMR1L = 0xEF;
TMR1H = 0xD8;
/* initialisation du TMR1 à 55 535 */
//Timer1 en service
PIR1.TMR1IF = 0; // clear TMR1IF
PORTB.F1 = 0;
PORTB.F0 = 0;
PORTB.F2 = 1;
CCPR1L = impulsionServoV;
CCPR1H = impulsionServoV>>8;
CCPR2L = impulsionServoH;
CCPR2H = impulsionServoH>>8;
//PORTE = 0;
//TRISE = 0; // set PORTD as output
/*
* initialize ethernet board
* start ENC28J60 with :
* reset bit on RC0
* CS bit on RC1
* my MAC & IP address
* full duplex
*/
Spi_Init();
SPI_Ethernet_Init(&PORTD, 0, &PORTD, 1, myMacAddr, myIpAddr, SPI_Ethernet_FULLDUPLEX) ;
while(1) // endless loop
{
SPI_Ethernet_doPacket() ; // process incoming Ethernet packets
/*
* add your stuff here if needed
* SPI_Ethernet_doPacket() must be called as often as possible
* otherwise packets could be lost
*/
}
}