error: (1089) recursive function call to "_forward_flight" XC8 compiler - c

I am trying to emulate a pingpong game with LED's showing the flight of the ball. Two players using buttons connected to RA0 and RA1 control the flight of the ball. Game starts with either pressing their respective button. I have two functions, forward_flight and reverse_flight which light the led's from player one two player 2 and vice versa. Player 2 has two return the ball by pressing his button when Led connected to RB7 is on and player 1 has to return the ball when led at RB0 is on. The game continues until one of them reaches a score of 9. I am using PORTB as output for the LED's. I am using PIC16F873A programming it in c. Below is the configuration and source code:
// PIC16F873A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#include <xc.h>
#define _XTAL_FREQ 20000
unsigned char x = 0;
unsigned char y = 0;
unsigned char h;
unsigned char sc;
unsigned char lookup(unsigned char sc);
void forward_flight();
void reverse_flight();
void game_Over();
void forward_flight(){
PORTBbits.RB0 = 1;
__delay_ms(50);
PORTBbits.RB0 = 0;
PORTBbits.RB1 = 1;
__delay_ms(50);
PORTBbits.RB1 = 0;
PORTBbits.RB2 = 1;
__delay_ms(50);
PORTBbits.RB2 = 0;
PORTBbits.RB3 = 1;
__delay_ms(50);
PORTBbits.RB3 = 0;
PORTBbits.RB4 = 1;
__delay_ms(50);
PORTBbits.RB4 = 0;
PORTBbits.RB5 = 1;
__delay_ms(50);
PORTBbits.RB5 = 0;
PORTBbits.RB6 = 1;
__delay_ms(50);
PORTBbits.RB6 = 0;
PORTBbits.RB7 = 1;
while(PORTBbits.RB7){
if(PORTAbits.RA1==1){
reverse_flight();
}
else if(PORTAbits.RA1==0){
__delay_ms(50);
PORTBbits.RB7 = 0;
x++;
if(x<=9){
PORTC = lookup(x);
}else{
game_Over();
break;
}
}
}
return;
}
void reverse_flight(){
PORTBbits.RB7 = 1;
__delay_ms(50);
PORTBbits.RB7 = 0;
PORTBbits.RB6 = 1;
__delay_ms(50);
PORTBbits.RB6 = 0;
PORTBbits.RB5 = 1;
__delay_ms(50);
PORTBbits.RB5 = 0;
PORTBbits.RB4 = 1;
__delay_ms(50);
PORTBbits.RB4 = 0;
PORTBbits.RB3 = 1;
__delay_ms(50);
PORTBbits.RB3 = 0;
PORTBbits.RB2 = 1;
__delay_ms(50);
PORTBbits.RB2 = 0;
PORTBbits.RB1 = 1;
__delay_ms(50);
PORTBbits.RB1 = 0;
PORTBbits.RB0 = 1;
while(PORTBbits.RB0){
if(PORTAbits.RA0==1){
forward_flight();
}
else if(PORTAbits.RA0==0){
__delay_ms(50);
PORTBbits.RB0 = 0;
y++;
if(y<=9){
PORTC = lookup(y);
}else{
game_Over();
break;
}
}
}
return ;
}
unsigned char lookup(unsigned char sc){
switch(sc){
case 0: sc = 0x00; break;
case 1: sc = 0x01; break;
case 2: sc = 0x02; break;
case 3: sc = 0x03; break;
case 4: sc = 0x04; break;
case 5: sc = 0x05; break;
case 6: sc = 0x06; break;
case 7: sc = 0x07; break;
case 8: sc = 0x08; break;
case 9: sc = 0x09; break;
}
return (sc);
}
void game_Over(){
x = 0;
y = 0;
}
void main(){
ADCON1 = 0xFF;
TRISAbits.TRISA0 = 1;
TRISAbits.TRISA1 = 1;
TRISB = 0x00;
PORTB = 0x00;
TRISC = 0x00;
PORTC = 0x00;
while(x <9 && y<9){
if(PORTAbits.RA0 == 1){
forward_flight();
}
else if(PORTAbits.RA1==1){
reverse_flight();
}
}
}
And this is the error I get.
source.c:14:: error: (1089) recursive function call to "_forward_flight"
source.c:66:: error: (1089) recursive function call to "_reverse_flight"
make[2]: *** [dist/default/production/Pingpong.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
(908) exit status = 1
nbproject/Makefile-default.mk:154: recipe for target 'dist/default/production/Pingpong.X.production.hex' failed
make[2]: Leaving directory 'C:/Users/PAKO MOARO/MPLABXProjects/Pingpong.X'
nbproject/Makefile-default.mk:91: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/PAKO MOARO/MPLABXProjects/Pingpong.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed

Related

why LCD does not display anything

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <string.h>
#include <stdint.h>
#include "config.h"
#include "Uart.h"
#define _XTAL_FREQ 20000000
#define RS RC0
#define EN RC1
#define D4 RC2
#define D5 RC3
#define D6 RC4
#define D7 RC5
/*
*
*/
void Lcd_Port(char a)
{
if(a & 1)
D4 = 1;
else
D4 = 0;
if(a & 2)
D5 = 1;
else
D5 = 0;
if(a & 4)
D6 = 1;
else
D6 = 0;
if(a & 8)
D7 = 1;
else
D7 = 0;
}
void Lcd_Cmd(char a)
{
RS = 0; // => RS = 0
Lcd_Port(a);
EN = 1; // => E = 1
__delay_ms(4);
EN = 0; // => E = 0
}
int Lcd_Clear()
{
Lcd_Cmd(0);
Lcd_Cmd(1);
}
void Lcd_Set_Cursor(char a, char b)
{
char temp,z,y;
if(a == 1)
{
temp = 0x80 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
else if(a == 2)
{
temp = 0xC0 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
}
void Lcd_Init()
{
Lcd_Port(0x00); // clear latches before enabling TRIS bits
__delay_ms(20);
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(11);
Lcd_Cmd(0x03);
/////////////////////////////////////////////////////
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x02);
Lcd_Cmd(0x08);//Select Row 1
Lcd_Cmd(0x00);//Clear Row 1 Display
Lcd_Cmd(0x0C);//Select Row 2
Lcd_Cmd(0x00);//Clear Row 2 Display
Lcd_Cmd(0x06);
}
void Lcd_Write_Char(char a)
{
char temp,y;
temp = a&0x0F;
y = a&0xF0;
RS = 1; // => RS = 1
Lcd_Port(y>>4); //Data transfer
EN = 1;
__delay_us(40);
EN = 0;
Lcd_Port(temp);
EN = 1;
__delay_us(40);
EN = 0;
}
void Lcd_Write_String(char *a)
{
int i;
for(i=0;a[i]!='\0';i++)
Lcd_Write_Char(a[i]);
}
void Lcd_Shift_Right()
{
Lcd_Cmd(0x01);
Lcd_Cmd(0x0C);
}
void Lcd_Shift_Left()
{
Lcd_Cmd(0x01);
Lcd_Cmd(0x08);
}
int main(int argc, char** argv) {
OSCCONbits.IRCF = 0b1111; //set operating frequency to 31kHz (0b1111) for 16MHz
UART_init();
Lcd_Init();
// ->Setare Pini
//Pini motor DC
ANSELAbits.ANSA0 = 0; //set to digital pin
ANSELAbits.ANSA1 = 0; //set to digital pin
TRISAbits.TRISA0 = 0; //set as output
TRISAbits.TRISA1 = 0; //set as output
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 0;
//Butoane
ANSELAbits.ANSA2 = 0; //set to digital pin
ANSELAbits.ANSA4 = 0; //set to digital pin
ANSELBbits.ANSB4 = 0; //set to digital pin
TRISAbits.TRISA2 = 1; //set as input
TRISAbits.TRISA4 = 1; //set as input
TRISBbits.TRISB4 = 1; //set as input
//LEDuri
//RC6 - RIGHT
//RC6 LEFT
TRISCbits.TRISC6 = 0;
TRISCbits.TRISC7 = 0;
//Set as digital
ANSELCbits.ANSC6 = 0;
ANSELCbits.ANSC7 = 0;
//Folosire LCD
TRISCbits.TRISC0 = 0; //set as output
TRISCbits.TRISC1 = 0; //set as output
TRISCbits.TRISC2 = 0; //set as output
TRISCbits.TRISC3 = 0; //set as output
TRISCbits.TRISC4 = 0; //set as output
TRISCbits.TRISC5 = 0; //set as output
//pull up
//pull upurile
OPTION_REGbits.nWPUEN = 0;
WPUAbits.WPUA2 = 1;
WPUAbits.WPUA4 = 1;
WPUAbits.WPUA0 = 1;
WPUAbits.WPUA1 = 0;
WPUAbits.WPUA3 = 0;
WPUAbits.WPUA5 = 0;
WPUBbits.WPUB4 = 1;
char introducere;
UART_write_string("1. Move to right ");
UART_write('\r');
UART_write_string("2. Move to left");
UART_write('\r');
UART_write_string("4. Stop UART");
UART_write('\r');
PORTCbits.RC6 = 0;
PORTCbits.RC7 = 0;
while(1){
introducere = UART_read();
if (introducere == '1'){
PORTAbits.RA0 = 1;
PORTAbits.RA1 = 0;
PORTCbits.RC6 = 1;
PORTCbits.RC7 = 0;
Lcd_Clear();
Lcd_Set_Cursor(1,1); //Go to the first line
Lcd_Write_String("helo"); //Display String
}
if (introducere == '2' ){
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 1;
PORTCbits.RC6 = 0;
PORTCbits.RC7 = 1;
}
if(PORTAbits.RA2 == 0){ //Right
PORTAbits.RA0 = 1;
PORTAbits.RA1 = 0;
PORTCbits.RC6 = 1;
PORTCbits.RC7 = 0;
}
if(PORTAbits.RA4 == 0){ //left
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 1;
}
if(introducere =='4'){
CREN = 0; //disable receiver
UART_write('\r');
UART_write_string("disable UART!");
UART_write('\r');
}
if(PORTBbits.RB4 == 0){
CREN = 1; //enable receiver
UART_write('\r');
UART_write_string("enable UART!");
UART_write('\r');
}
}
return (EXIT_SUCCESS);
}
The purpose of the project is to create a Dc motor which when we press 1 to rotate to the right and display on the LCD "rotated right", and if we press 2 to rotate to the left and display on the LCD "rotate left".
Used: pic16f1828
LCD: LM016L
I connected: RS (LCD) -> RC0 (pic), EN -> RC1, D4 -> RC2, D5 -> RC3, D6 -> RC4, D7 -> RC5
The program works well, the only problem I have is the fact that when I press "1" I want HELO to appear on LCD (it doesn't matter the arrangement). Till now it does not appear on LCD, is not just about HELLo, nothing is displayed, I can only see that it starts, I don't understand where the problem is.
Your implementation for writing to the HD44780 using a 4-bit parallel interface is wrong.
This is a complete, builds with MPLABX v5.50 and XC8 v2.32, demo that does display "Hello" on line 1 of the LCD module:
/*
* File: main.c
* Author: dan1138
* Target: PIC16F1828
* Compiler: XC8 v2.32
* IDE: MPLABX v5.50
*
* Created on January 23, 2022, 11:27 AM
*
* PIC16F1828
* +-----------:_:-----------+
* VDD -> : 1 VDD VSS 20 : <- VSS
* RA5 <> : 2 OSC2 PGD 19 : <> RA0 ICD_PGD
* RA4 <> : 3 OSC1 PGC 18 : <> RA1 ICD_PGC/D5
* ICD_VPP RA3 -> : 4 VPP/MCLRn 17 : <> RA2
* LCD_D7 RC5 <> : 5 16 : <> RC0 LCD_RS
* LCD_D6 RC4 <> : 6 15 : <> RC1 LCD_EN
* LCD_D5 RC3 <> : 7 14 : <> RC2 LCD_D4
* RC6 <> : 8 13 : <> RB4
* RC7 <> : 9 12 : <> RB5
* RB7 <> : 10 11 : <> RB6
* +-------------------------+
* DIP-20
*
* Description:
*
* See: https://stackoverflow.com/questions/70800375/why-lcd-does-not-display-anything
*/
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
/*
* Tell compiler what we intend to set the system oscillator frequency as.
*/
#define _XTAL_FREQ (16000000UL)
#include <xc.h>
#include <stdio.h>
/* Define the LCD interface and character size */
#define LCD_FORMAT (FOUR_BIT & LINES_5X7)
/* Define the LCD port pins */
#define LCD_DATA_BITS_MASK 0x3C
#define LCD_PORT_OUT LATC
#define LCD_PORT_DIR TRISC
#define LCD_RS_PIN LATCbits.LATC0
#define LCD_EN_PIN LATCbits.LATC1
#define LCD_D4_PIN LATCbits.LATC2
#define LCD_D5_PIN LATCbits.LATC3
#define LCD_D6_PIN LATCbits.LATC4
#define LCD_D7_PIN LATCbits.LATC5
#define LCD_RS_PIN_DIR TRISCbits.TRISC0
#define LCD_EN_PIN_DIR TRISCbits.TRISC1
#define LCD_D4_DIR TRISCbits.TRISC2
#define LCD_D5_DIR TRISCbits.TRISC3
#define LCD_D6_DIR TRISCbits.TRISC4
#define LCD_D7_DIR TRISCbits.TRISC5
/* Clear display command */
#define CLEAR_DISPLAY 0b00000001
/* Return home command */
#define RETURN_HOME 0b00000010
/* Display ON/OFF Control defines */
#define DON 0b00001111 /* Display on */
#define DOFF 0b00001011 /* Display off */
#define CURSOR_ON 0b00001111 /* Cursor on */
#define CURSOR_OFF 0b00001101 /* Cursor off */
#define BLINK_ON 0b00001111 /* Cursor Blink */
#define BLINK_OFF 0b00001110 /* Cursor No Blink */
/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT 0b00010011 /* Cursor shifts to the left */
#define SHIFT_CUR_RIGHT 0b00010111 /* Cursor shifts to the right */
#define SHIFT_DISP_LEFT 0b00011011 /* Display shifts to the left */
#define SHIFT_DISP_RIGHT 0b00011111 /* Display shifts to the right */
/* Function Set defines */
#define FOUR_BIT 0b00101111 /* 4-bit Interface */
#define EIGHT_BIT 0b00111111 /* 8-bit Interface */
#define LINE_5X7 0b00110011 /* 5x7 characters, single line */
#define LINE_5X10 0b00110111 /* 5x10 characters */
#define LINES_5X7 0b00111011 /* 5x7 characters, multiple line */
/* Start address of each line */
#define LINE_ONE 0x00
#define LINE_TWO 0x40
static void LCD_E_Pulse(void)
{
LCD_EN_PIN = 1;
__delay_us(4);
LCD_EN_PIN = 0;
__delay_us(4);
}
static void LCD_DelayPOR(void)
{
__delay_ms(15);
}
static void LCD_Delay(void)
{
__delay_ms(5);
}
static void LCD_PutByte(unsigned char LCD_Data)
{
LCD_PORT_DIR &= ~LCD_DATA_BITS_MASK; /* make LCD data bits outputs */
/* send first(high) nibble */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;
if(LCD_Data & 0x10) LCD_D4_PIN = 1;
if(LCD_Data & 0x20) LCD_D5_PIN = 1;
if(LCD_Data & 0x40) LCD_D6_PIN = 1;
if(LCD_Data & 0x80) LCD_D7_PIN = 1;
LCD_E_Pulse();
/* send second(low) nibble */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;
if(LCD_Data & 0x01) LCD_D4_PIN = 1;
if(LCD_Data & 0x02) LCD_D5_PIN = 1;
if(LCD_Data & 0x04) LCD_D6_PIN = 1;
if(LCD_Data & 0x08) LCD_D7_PIN = 1;
LCD_E_Pulse();
LCD_PORT_DIR |= LCD_DATA_BITS_MASK; /* make LCD data bits inputs */
}
void LCD_SetPosition(unsigned char data)
{
LCD_RS_PIN = 0;
LCD_PutByte((unsigned char)(data | 0x80));
__delay_us(40);
}
void LCD_WriteCmd(unsigned char data)
{
LCD_RS_PIN = 0;
LCD_PutByte(data);
__delay_ms(4);
}
void LCD_WriteData(unsigned char data)
{
LCD_RS_PIN = 1;
LCD_PutByte(data);
LCD_RS_PIN = 0;
__delay_us(40);
}
void LCD_Init(void)
{
unsigned char LCD_Data;
LCD_PORT_DIR &= ~LCD_DATA_BITS_MASK; /* make LCD data bits outputs */
LCD_EN_PIN_DIR = 0; /* make LCD Enable strobe an output */
LCD_RS_PIN_DIR = 0; /* make LCD Register select an output */
LCD_EN_PIN = 0; /* set LCD Enable strobe to not active */
LCD_RS_PIN = 0; /* set LCD Register select to command group */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK; /* set LCD data bits to zero */
LCD_DelayPOR(); /* wait for LCD power on to complete */
/* Force LCD to 8-bit mode */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK; /* set LCD data bits to zero */
LCD_D4_PIN = 1;
LCD_D5_PIN = 1;
LCD_E_Pulse();
LCD_Delay();
LCD_E_Pulse();
LCD_Delay();
LCD_E_Pulse();
LCD_Delay();
/* Set LCD to 4-bit mode */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK; /* set LCD data bits to zero */
LCD_D5_PIN = 1;
LCD_E_Pulse();
LCD_Delay();
/* Initialize LCD mode */
LCD_WriteCmd(LCD_FORMAT);
/* Turn on display, Setup cursor and blinking */
LCD_WriteCmd(DOFF & CURSOR_OFF & BLINK_OFF);
LCD_WriteCmd(DON & CURSOR_OFF & BLINK_OFF);
LCD_WriteCmd(CLEAR_DISPLAY);
LCD_WriteCmd(SHIFT_CUR_LEFT);
/* Set first position on line one, left most character */
LCD_SetPosition(LINE_ONE);
}
/*
* Hook for printf
*/
void putch(char txData)
{
LCD_WriteData(txData);
}
/*
* Main application
*/
void main(void)
{
OSCCON = 0x7A; //set operating frequency to 16MHz
ANSELA = 0;
ANSELB = 0;
ANSELC = 0;
//pull up
OPTION_REGbits.nWPUEN = 0;
WPUAbits.WPUA2 = 1;
WPUAbits.WPUA4 = 1;
WPUAbits.WPUA0 = 1;
WPUAbits.WPUA1 = 0;
WPUAbits.WPUA3 = 0;
WPUAbits.WPUA5 = 0;
LCD_Init();
__delay_ms(100);
LCD_SetPosition(LINE_ONE);
printf("Hello");
/*
* Application loop
*/
for(;;)
{
}
}

Debounce button in PIC

I newbie in PIC mcu. I use pic12f675 MPLAB and XC8 for make an LED multiple blink pattern.
and I have problem with push button (after review it call Bounce and Debounce).
Sometime when I press button it will in sequence ex. 1->2->3->4->5 but sometime it will jump ex. 1->3->4->6 etc.
Please advice me How to debounce in pic mcu or another way to solve my problem.
Thank you. everyone.
(PS.I connect push button with 10K resistor)
my code at below
#include <xc.h>
#pragma config FOSC=INTRCIO,WDTE=OFF,MCLRE=OFF,BOREN=OFF
#define _XTAL_FREQ 4000000
int cnt = 0;
int k = 0;
void __interrupt() MyISR(void){
if(INTCONbits.INTF) //If External Edge INT Interrupt
{
cnt++;
INTCONbits.GIE = 0;
INTCONbits.INTF = 0; // Clear the interrupt
INTCONbits.GPIF = 0;
if( cnt > 6 ){
cnt = 1;
}
}
INTCONbits.GIE = 1;
}
void main(void) {
ANSEL = 0;
CMCON = 0b00000111; //turns comparators off
TRISIO = 0b00000100;
GPIO = 0;
TRISIO2 = 1; // Make GP2 pin as input
INTCONbits.GIE = 1;
INTCONbits.INTE = 1;
INTCONbits.GPIF = 1;
INTCONbits.INTF = 0;
OPTION_REG = 0b01000000;
while(1){
if( cnt == 1 ){
GP0 = 1;
GP5 = 1;
}else if( cnt == 2 ){
for(k=0;k<30;k++){
GP5 = 1;
GP0 = 1;
}
k=0;
while(k<3){
GP5 = ~GP5;
__delay_ms(70);
GP0 = ~GP0;
__delay_ms(70);
k++;
}
}else if( cnt == 3 ){
for(k=0;k<5;k++){
GP5 = 1;
GP0 = 1;
__delay_ms(70);
GP5 = 0;
GP0 = 0;
__delay_ms(70);
}
GP5 = 0;
GP0 = 0;
__delay_ms(1200);
}else if( cnt == 4 ){
for(k=0;k<3;k++){
GP0 = 1;
__delay_ms(50);
GP0 = 0;
__delay_ms(50);
}
for(k=0;k<3;k++){
GP5 = 1;
__delay_ms(50);
GP5 = 0;
__delay_ms(50);
}
}else if( cnt == 5 ){
GP0 = 1;
GP5 = 1;
for(k=0;k<3;k++){
GP5 = 1;
__delay_ms(50);
GP5 = 0;
__delay_ms(50);
}
GP0 = 1;
GP5 = 1;
for(k=0;k<3;k++){
GP0 = 1;
__delay_ms(50);
GP0 = 0;
__delay_ms(50);
}
}else if( cnt == 6 ){
GP0 = 1;
GP5 = 1;
__delay_ms(20);
GP0 = 0;
GP5 = 0;
__delay_ms(3000);
}
}
return;
}
I rewrite your code and tested it in MPLAB simulation. It works as expected. It changes modes in ascending order, then runs in the selected mode until the change button pressed again, then it changes to the next mode. You can add more working modes if you want or you can modify the way the how GPIOs blinking. There is no __delay_ms(), that's why the delays run without consuming the CPU. Please test it in a real circuit and give me a feedback.
/*
* File: main.c
* Author: kozmotronik
*
*/
#define _XTAL_FREQ 4000000
#include <xc.h>
#include <stdint.h>
#include <stdbool.h>
#pragma config FOSC=INTRCIO,WDTE=OFF,MCLRE=OFF,BOREN=OFF
// Work mode definitions
#define MODE_IDLE 0
#define MODE_OFF 1
#define MODE_ON 2
#define MODE_SLOW 3
#define MODE_FAST 4
#define MODE_CANCEL 5
#define LAST_MODE MODE_FAST
// Button states
#define BUTTON_IDLE 0
#define BUTTON_PRESS_DETECTED 1
#define BUTTON_DEBOUNCING 2
#define BUTTON_PRESS_CONFIRMED 3
#define SYSTEM_CLOCK_MS 1
#define SYSTEM_CLOCK_uS (SYSTEM_CLOCK_MS * 1000)
#define _XTAL_FREQ_MHZ (_XTAL_FREQ / 1000000) // Oscillator freq in MHz
#define TMR0_RELOAD_VALUE 256 - ( (SYSTEM_CLOCK_uS * _XTAL_FREQ_MHZ) / (8 * 4) ) // Result must be 131
#define MS_TO_TICKS(msTime) (msTime / SYSTEM_CLOCK_MS)
typedef struct{
unsigned int start;
unsigned int ticks;
} time_t;
char mode = MODE_IDLE;
char lastMode = MODE_OFF;
char buttonState = BUTTON_IDLE;
char k = 0;
unsigned int systemTick = 0; // Time value count by Timer0
void __interrupt() MyISR(void){
if(INTCONbits.INTF) //If External Edge INT Interrupt
{
INTCONbits.INTF = 0; // Clear the interrupt
buttonState = BUTTON_PRESS_DETECTED; // Signal the detected press
}
// Check for 1 ms periodic interrupt for system clock
else if(INTCONbits.T0IF){
INTCONbits.T0IF = 0; // clear flag
TMR0 = TMR0_RELOAD_VALUE; // Reload the calculated value for 1 ms
systemTick++;
}
}
// Setup Timer0 for 1ms interrupt
void setupTimer0(){
#define PRESCALER_VALUE 2
#define PRESCALER_MASK ~7
OPTION_REG &= PRESCALER_MASK; // Clear prescaler bits
OPTION_REG |= PRESCALER_VALUE; // Set prescaler value for 1:8
OPTION_REGbits.PSA = 0; // Assign prescaler to Tim0
OPTION_REGbits.T0CS = 0; // Set internal oscillator as clock source
TMR0 = TMR0_RELOAD_VALUE;
INTCONbits.T0IF = 0;
INTCONbits.T0IE = 1; // Enable Timer0 interrupt
}
// Get count atomically
unsigned int getTickCount(){
unsigned int count;
di(); // disable interrupts
count = systemTick;
ei(); // enable interrupts again
return count;
}
void performMode(){
static time_t modeDelay;
static char slowModeState = 1;
static char fastModeState = 1;
switch(mode){
case MODE_OFF:
// Always must save the current mode before put it into the IDLE
lastMode = mode; // We have to save the last mode first then put it into the IDLE state
mode = MODE_IDLE; // The rollover bug caused by here since we haven't save the last mode before put it into the IDLE state
GP0 = 0; GP5 = 0;
break;
case MODE_ON:
GP0 = 1; GP5 = 1;
break;
case MODE_SLOW:
if(slowModeState == 1){
GP0 = 1; GP5 = 1;
modeDelay.ticks = MS_TO_TICKS(100);
modeDelay.start = getTickCount();
slowModeState = 2; // Proceed the next step
}
else if(slowModeState == 2){
if( !((getTickCount() - modeDelay.start) >= modeDelay.ticks) ){
// Delay not expired yet
return;
}
GP0 = ~GP0; GP5 = ~GP5; // Toggle
// Reload the start time
modeDelay.start = getTickCount();
}
break;
case MODE_FAST:
if(fastModeState == 1){
GP0 = 1; GP5 = 1;
modeDelay.ticks = MS_TO_TICKS(50);
modeDelay.start = getTickCount();
fastModeState = 2; // Proceed the next step
}
else if(fastModeState == 2){
if( !((getTickCount() - modeDelay.start) >= modeDelay.ticks) ){
// Delay not expired yet
return;
}
// Delay time expired, proceed toggle
GP0 = ~GP0; GP5 = ~GP5; // Toggle
// Reload the start time
modeDelay.start = getTickCount();
}
break;
case MODE_CANCEL:
// Cancel the current running mode, reset everything
modeDelay.start = 0;
modeDelay.ticks = 0;
slowModeState = 1;
fastModeState = 1;
// Also reset the outputs
GP0 = 0; GP5 = 0;
break;
default:
mode = MODE_IDLE;
}
}
void checkButton(){
#define DEBOUNCE_DELAY_MS 100u // Debounce delay is 100 ms
static time_t debounceTimer;
switch(buttonState){
case BUTTON_IDLE:
break;
case BUTTON_PRESS_DETECTED:
debounceTimer.ticks = MS_TO_TICKS(DEBOUNCE_DELAY_MS);
debounceTimer.start = getTickCount();
buttonState = BUTTON_DEBOUNCING;
break;
case BUTTON_DEBOUNCING:
if( !((getTickCount() - debounceTimer.start) >= debounceTimer.ticks) ){
// Debounce time has not expired yet
return;
}
// Debounce time has expired so check the button last time to confirm if it is still pressed
if(GPIObits.GP2 != 1){
// Not stable yet, debounce again
buttonState = BUTTON_PRESS_DETECTED;
}
// Button press is stable, confirm it
buttonState = BUTTON_PRESS_CONFIRMED;
break;
case BUTTON_PRESS_CONFIRMED:
buttonState = BUTTON_IDLE; // Change state so that it can process a new button press
if(mode != MODE_IDLE && mode != MODE_OFF){
// Cancel the running mode first
lastMode = mode; // save the last mode
mode = MODE_CANCEL; // purge the current one
performMode();
}
mode = lastMode + 1; // Switch to next mode
if(mode > LAST_MODE){
// Rewind mode to the beginning which is MODE_OFF
mode = MODE_OFF;
}
break;
default:
buttonState = BUTTON_IDLE;
}
}
void main(void) {
ANSEL = 0;
CMCON = 0b00000111; //turns comparators off
TRISIO = 0b00000100;
GPIO = 0;
TRISIO2 = 1; // Make GP2 pin as input
INTCONbits.INTF = 0;
INTCONbits.INTE = 1;
INTCONbits.GIE = 1;
OPTION_REG = 0b01000000; // Rising edge interrupt
setupTimer0();
// Super loop
while(1){
// Task 1: Button check
if(buttonState != BUTTON_IDLE){
checkButton();
}
// Task 2: Mode check
else if(mode != MODE_IDLE){
performMode();
}
}
return;
}

Why pic18f46k40 Timer0 overflow doesn't occur

I am using the debug function to check the TMR0IF flag but it doesn't occur. It is stuck at while(PIR0bits.TMR0IF ==0). Please advise.
#define _XTAL_FREQ 64000000
#define ACM_STEP_TRIS TRISAbits.TRISA4
#define ACM_STEP LATAbits.LATA4
#define ACM_ENABLE_TRIS TRISAbits.TRISA5
#define ACM_nENABLE LATAbits.LATA5
ACM_STEP_TRIS =0;
void main(void)
{
T0CON0bits.T0OUT = 0;
T0CON0bits.T016BIT = 1; // TMR0 is a 16-bit timer
T0CON0bits.T0OUTPS = 0; // No prescaler
T0CON1bits.T0CS =0b010; //Clock source is Fosc/4
T0CON1bits.T0ASYNC =0; //Input to TMR0 counter is synchronized to Fosc/4
T0CON1bits.T0CKPS =0; //Prescaler 1:1
while (1){
ACM_nENABLE =0; // Turn on stepper motor
__delay_ms(2);
ACM_STEP ^=1;
TMR0H = 0xFD;
TMR0L = 0xE8; // Load TMR0L
T0CON0bits.T0EN = 1; //Timer Module is enabled
while(PIR0bits.TMR0IF ==0);
T0CON0bits.T0EN = 0; //Turn off Timer
PIR0bits.TMR0IF = 0; // Clear TF0 flag
}
return;
}
Please check out this answer: http://www.edaboard.com/showthread.php?t=197899
They checks another register (INTCONbits and not PIR0bits) and everything works ok.

How to change LED flashing pattern by sw

I currently use PIC16F1827 to tact sw to led blinking pattern
We are creating a program to switch.
The input of sw is RA0, and when you press the button, it drops to Low.
In creating the program There is one problem.
For example, press sw while processing pat1 ();
There are times when I want to switch to the next lighting mode.
However, until the processing of pat1 (); is finished, the blinking pattern
It will not switch.
Is there a way to switch the flashing pattern at the moment you press sw?
Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#define _XTAL_FREQ 4000000
/*
* CONFIG will be omitted
*/
void internal_osc();
void io_int();
void tmr0_int();
void sw_scan();
void pat1();
void pat2();
void pat3();
void pat4();
char tmr0_cnt;
char sw_data;
char SwStatus;
char cnt;
void main(void){
internal_osc();
io_int();
tmr0_int();
while(1){
//sw_scan();
switch(sw_data){
case 1 :
pat1();
break;
case 2 :
pat2();
break;
case 3 :
pat3();
break;
case 4 :
pat4();
break;
default :
PORTB = 0x00;
break;
}
}
}
void interrupt ISR(void){
INTCONbits.TMR0IF = 0;
TMR0 = 130;
cnt++;
if(cnt>=15){
cnt=0;
sw_scan();
}
}
void internal_osc(void){
OSCCON = 0x6a;
}
void io_int(void){
TRISA = 0x01;
TRISB = 0x00;
ANSELA = 0x00;
ANSELB = 0x00;
}
void tmr0_int(void){
OPTION_REG = 0x82;
TMR0 = 130;
INTCONbits.TMR0IE = 1;
INTCONbits.GIE = 1;
}
void sw_scan(void){
if(PORTAbits.RA0 == 0){
__delay_ms(10);
if(PORTAbits.RA0 == 0){
if(SwStatus==0){
SwStatus = 1;
if(sw_data>4){
sw_data = 0;
}
sw_data++;
}
}
else{
SwStatus = 0;
}
}
else{
SwStatus = 0;
}
}
void pat1(void){
PORTB = 0x01;
__delay_ms(500);
PORTB = 0x02;
__delay_ms(500);
PORTB = 0x04;
__delay_ms(500);
PORTB = 0x08;
__delay_ms(500);
}
void pat2(void){
PORTB = 0x01;
__delay_ms(500);
PORTB = 0x03;
__delay_ms(500);
PORTB = 0x07;
__delay_ms(500);
PORTB = 0x0f;
__delay_ms(500);
}
void pat3(void){
PORTB = 0x0e;
__delay_ms(500);
PORTB = 0x0d;
__delay_ms(500);
PORTB = 0x0b;
__delay_ms(500);
PORTB = 0x07;
__delay_ms(500);
}
void pat4(void){
PORTB = 0x0e;
__delay_ms(500);
PORTB = 0x0c;
__delay_ms(500);
PORTB = 0x08;
__delay_ms(500);
PORTB = 0x00;
__delay_ms(500);
}
The problem with your design is that the CPU spends most of the time stuck in the __delay_ms() loops. It cannot respond to button pushes while it is busy counting through multiple calls to __delay_ms(500).
The solution is don't use a busy-loop to pass time. Instead, you have to allow the CPU to respond to other events while you monitor the passage of time. One way to do this is to record the timer tick count at the time of an event. And then repeatedly compare that previous tick value with the timer's current tick value within your while loop (while you continue to do other things such as checking whether the switch was pressed).
Since you have a __delay_ms() function, you probably have access to another function to get the timer's current tick value. In the example below I've assumed that this function is called __get_tick() but it may have a different name.
I've also taken the liberty of reducing all of your pattern functions into a multidimensional array. But don't get too distracted by that. The real solution I'm recommending is to use __get_tick() instead of __delay_ms().
#define NUM_PATTERNS 5
#define NUM_STEPS 4
uint8_t const patterns[NUM_PATTERNS][NUM_STEPS] = {
{0x00, 0x00, 0x00, 0x00}, // LEDs are off
{0x01, 0x02, 0x04, 0x08}, // pattern 1
{0x01, 0x03, 0x07, 0x0f}, // pattern 2
{0x0e, 0x0d, 0x0b, 0x07}, // pattern 3
{0x0e, 0x0c, 0x08, 0x00} // pattern 4
};
void main(void){
int current_pattern = 0;
int current_step = 0;
char prev_sw_data = 0;
uint32_t prev_tick = 0;
internal_osc();
io_int();
tmr0_int();
while(1){
bool was_switch_pressed = false;
bool has_500_ms_passed = false;
uint32_t current_tick = __get_tick();
// Check whether the switch has been pressed.
if (sw_data != prev_sw_data) {
was_switch_pressed = true;
// Remember the new sw_data setting.
prev_sw_data = sw_data;
// Change the pattern.
current_pattern = sw_data;
// Start at step 0 whenever the switch is pressed and
// the pattern is changed.
current_step = 0;
}
else {
// Check whether 500 ms has passed.
if ( (current_tick - prev_tick) > NUM_TICKS_IN_500_MS) )
{
has_500_ms_passed = true;
// Advance to the next step in the pattern
++current_step;
if (current_step >= NUM_STEPS) {
current_step = 0;
}
}
}
if (was_switched_pressed || has_500_ms_passed)
{
// Remember the new tick time.
prev_tick = current_tick;
PORTB = patterns[current_pattern][current_step];
}
}
}
The problem is that you are blocking the while(1) loop when you are in a pattern
One idea is to make the counter and give you a tact each 1ms and make the following change:
while(1){
check_if_50ms_passed{
switch(sw_data){
case 1 : pat1(); break;
case 2 : pat2(); break;
case 3 : pat3(); break;
case 4 : pat4(); break;
default : PORTB = 0x00;break;
}
}
}
You must keep a counter in each pattern:
void pat1(void){
couter_for_next_step++;
if(couter_for_next_step == 10)// 50ms * 10 steps = 500ms
{
couter_for_next_step = 0;
switch(port_change){
case 1 : PORTB = 0x01; break;
case 2 : PORTB = 0x02; break;
case 3 : PORTB = 0x04; break;
case 4 : PORTB = 0x08; break;
default: break;
}
}
and when you change the sw_data do not forget to:
couter_for_next_step = 10;
port_change = 1;
This will allow you to enter through the while(1) loop several times and also check the status of the pressed button
You can also add at a pressed button event to turn off the leds
you can use a ( high priority software ) interrupt for this
on a processor or OS that is able for multithreading you could use different threads, on a PIC you can use interrupts

Controlling a DC motor with a PIC 18 PWM

Im using the PIC 18 microcontroller to control the speed of a DC Motor using PWM. I have managed to get it to spin using the code below. And I have tested that my H-Bridge is 100% functional.
However, when I switch on my circuit, 12V to the Motor and 5V to the logic, And I send a command to the circuit using my RS232 communication module, (which I have tested and it recieves and transmits correctly), the program resets and the current on the bench power supply falls to 0A. Sometimes the motor jerks slighty, almost as if its trying to spin, but then stops.
Any ideas where I could be going wrong?
/*
* File: serial.c
* Author: Chris Lombaard
*
* Created on September 13, 2013, 2:39 PM
*/
#pragma config FOSC = INTIO7 // Oscillator Selection bits (Internal oscillator block, CLKOUT function on OSC2)
#pragma config PLLCFG = OFF // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = ON // Primary clock enable bit (Primary clock is always enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 190 // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)
#pragma config WDTEN = OFF // Watchdog Timer Enable bits (WDT is always enabled. SWDTEN bit has no effect)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
#pragma config CCP2MX = PORTC1 // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<5:0> pins are configured as analog input channels on Reset)
#pragma config CCP3MX = PORTB5 // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0 // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTD2 // ECCP2 B output mux bit (P2B is on RD2)
#pragma config MCLRE = EXTMCLR // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled if MCLRE is also 1)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)
#include <P18F45K22.h>
#include <xc.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000
#define length(x) (sizeof(x) / sizeof(x[0])) //Length of array
void writeUART(const unsigned char string[]);
void setup(void);
void inputCheck(void);
void stepF(void);
void stepB(void);
unsigned char buffer[8] = {'\0'};
unsigned char prevPos = 0;
unsigned char currPos = 0;
unsigned char bufferLength;
unsigned char direction = 0;
unsigned char speed = 0;
unsigned char isSetup = 0;
char main(void){
if(isSetup == 0){
setup();
writeUART("ERD 320 Practical 2 ----- Group 1\n");
writeUART("JC Lombaard - 11028786\n");
writeUART("VFDC Henriques - 11100232\n");
writeUART("William Reeler - 11228866\n");
writeUART("FAN POSITION: 1");
PORTDbits.RD1 = 1;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
PORTAbits.RA6 = 0;
}
while(1){
if(PORTEbits.RE1 == 1)
stepB();
if(PORTEbits.RE0 == 1){
writeUART("\nFan calibrated!\n");
break;
}
}
bufferLength = 0;
while (1);
return (EXIT_SUCCESS);
}
void interrupt high_priority isr_high(void) {
if(PIR1bits.RC1IF == 1){
if(RCREG1 == '\n'){
buffer[bufferLength++] = '\0';
bufferLength = 0;
inputCheck();
}else{
buffer[bufferLength++] = RCREG1;
PIR1bits.RC1IF = 0;
}
}
}
void interrupt low_priority isr_low(void){
PIR1bits.TMR2IF = 0;
TMR2 = 0;
}
void inputCheck(void) {
const unsigned char commands[11][3] = {"S0", "S1", "S2", "S3", "S4", "P1", "P2", "P3", "P4", "R", "F"};
unsigned char choice = 0;
for(; choice < 11; choice++)
if (strcmp(buffer, commands[choice]) == 0){
break;
}
switch(choice){
case 0:
writeUART("FAN SPEED: 0% DC");
PORTA = 0b00111111;
speed = 0;
if(direction == 0){
CCPR1L = 0x00;
}else{
CCPR2L = 0x00;
}
break;
case 1:
writeUART("FAN SPEED: 10% DC");
PORTA = 0b00000110;
speed = 0b01101110 ;
if(direction == 0){
CCPR1L = 0b11010000 ;
__delay_ms(100);
CCPR1L = 0b01101110 ;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b01101110 ;
}
break;
case 2:
writeUART("FAN SPEED: 30% DC");
PORTA = 0b01011011;
speed = 0b10001100;
if(direction == 0){
CCPR1L = 0b11010000;
__delay_ms(100);
CCPR1L = 0b10001100;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b10001100 ;
}
break;
case 3:
writeUART("FAN SPEED: 60% DC");
PORTA = 0b01001111;
speed = 0b10101101;
if(direction == 0){
CCPR1L = 0b11010000 ;
__delay_ms(100);
CCPR1L = 0b10101101 ;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b10101101 ;
}
break;
case 4:
writeUART("FAN SPEED: 90% DC");
PORTA = 0b01100110;
speed = 0b11010000 ;
if(direction == 0){
CCPR1L = 0b11010000;
}else{
CCPR2L = 0b11010000;
}
break;
case 5:
currPos = 1;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
}
writeUART("FAN POSITION: 1");
PORTDbits.RD1 = 1;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 6:
prevPos = currPos;
currPos = 2;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 2");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 1;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 7:
prevPos = currPos;
currPos = 3;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 3");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 1;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 8:
prevPos = currPos;
currPos = 4;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 4");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 1;
prevPos = currPos;
break;
case 9:
direction = 1;
CCP1CON = 0b00000000;
CCP2CON = 0b00111100;
CCPR2L = speed;
writeUART("FAN DIRECTION: REVERSED");
break;
case 10:
direction = 0;
CCP1CON = 0b00111100;
CCP2CON = 0b00000000;
CCPR1L = speed;
writeUART("FAN DIRECTION: FORWARD");
break;
default:
break;
}
}
void stepF(void){
for(int i = 0; i < 1; i++){
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
}
}
void stepB(void){
for(int i = 0; i < 1; i++){
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
}
}
void defaultPos(void){
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
}
void writeUART(const unsigned char string[]){
for(unsigned char j = 0; j < strlen(string); j++){
TXREG1 = string[j];
__delay_us(1000);
}
}
void setup(void){
isSetup = 1;
//PORTC
PORTC = 0x00;
LATC = 0x00;
TRISC = 0xC0; //Set RC6 & RC7 as inputs for EUSART
TRISCbits.RC6 = 0;
TRISCbits.RC7 = 1;
ANSELC = 0x00;
//PORTD
PORTD = 0x00;
LATD = 0x00;
TRISD = 0x00;
ANSELD = 0x00;
//PORTE
PORTE = 0x00;
LATE = 0x00;
TRISEbits.RE0 = 1;
TRISEbits.RE1 = 1;
ANSELE = 0x00;
//PORTB
PORTB = 0x00;
LATB = 0x00;
TRISB = 0x00;
ANSELB = 0x00;
PORTA = 0x00;
LATA = 0x00;
TRISA = 0x00;
ANSELA = 0x00;
//Oscillator
OSCCON = 0b01011100; //4 MHz oscillator
//EUSART
TXSTA1bits.BRGH = 1; //Highspeed baudrate
BAUDCON1bits.BRG16 = 0;
SPBRG1 = 12; //Baudrate of 19230 (FOSC = 4 MHz, BRGH = 1, BRG16 = 0)
TXSTA1bits.SYNC = 0; //Asynchronous
RCSTA1bits.SPEN = 1; //Enable rx & tx pins as serial pins
RCSTA1bits.CREN = 1; //Enable continuous reception, enable receiver
TXSTA1bits.TXEN = 1; //Enable transmitter
TXREG1 = 0x00;
RCREG1 = 0x00;
//Interrupts
RCONbits.IPEN = 1; //Enable priorities
INTCONbits.GIE_GIEH = 1; //Enable high priority interrupts
INTCONbits.PEIE_GIEL = 1; //Enable low priority interrupts
PIE1bits.TMR2IE = 1;
IPR1bits.TMR2IP = 0;
PIE1bits.RC1IE = 1; //Enable RX interrupt
PIR1bits.RC1IF = 0; //Clear interrupt flag
IPR1bits.RC1IP = 1; //High priority for RX interrupts
//PWM
PR2 = 0b11111001 ;
T2CON = 0b00000100; //1 KHz pulse frequency on CCP1 pin
CCPR1L = 0x00;
CCPR2L = 0x00;
CCP1CON = 0b00111100;
CCP2CON = 0b00000000;
TMR2 = 0;
}
A few suggestions,
Oscilliscope?
test with a light bulb rather than a DC motor, less current and voltage drop
this smells like a hardware problem

Resources