alpha91
Full Member level 3
- Joined
- Sep 23, 2011
- Messages
- 168
- Helped
- 1
- Reputation
- 2
- Reaction score
- 2
- Trophy points
- 1,298
- Activity points
- 2,625
signed int i = 0;
void InitTimer1()
{
T1CON = 0x31;
TMR1IF_bit = 0;
TMR1IE_bit = 1;
INTCON = 0xC0; //
}
void Interrupt() {
if(TMR1IF_bit)
{
for(i = 0; i < 256; i += 10) // LED is glowing with delay by using timer
{
PWM1_Set_Duty(i);
TMR1H = 0x4E; // set timer
TMR1L = 0x20; // set timer
}
for(i = 250; i >= 0; i -= 10) // LED is fade out with delay by using timer
{
PWM1_Set_Duty(i);
TMR1H = 0x4E; // set timer
TMR1L = 0x20; // set timer
}
TMR1IF_bit = 0;// reset trigger bit
}
}
void main()
{
TRISB = 0x00;// B3 PWM output
PWM1_Init(5000); // Initialize PWM frequency
//PWM1_Set_Duty(127);
PWM1_Start();
while (1) {
}
}
/*
* File: main_xc8.c
* Target: PIC16F628A
* Compiler: XC8 v1.45
*
* Description:
* Use the PWM output to fade an LED on and off.
*
* PIC16F628A
* +----------:_:----------+
* <> 1 : RA2 RA1 : 18 <>
* <> 2 : RA3 RA0 : 17 <>
* <> 3 : RA4(*) OSC1/RA7 : 16 <>
* VPP -> 4 : RA5/VPP OSC2/RA6 : 15 <>
* GND -> 5 : VSS VDD : 14 <- 5v0
* <> 6 : RB0 PGD/RB7 : 13 <> PGD
* <> 7 : RB1/RX/DT PGC/RB6 : 12 <> PGC
* <> 8 : RB2/RX/CK RB5 : 11 <>
* LED <- 9 : RB3/CCP1 PGM/RB4 : 10 <>
* +-----------------------:
* DIP-18
* Notes:
* (*) RA4 is an open drain output. Requires an external pull-up for output.
*/
#include <xc.h>
// PIC16F628A Configuration Bit Settings
// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 4000000ul
#define INTCON_T0IF_MASK (1<<2)
#define CCP1_CCP1M_PWM_MODE (0b1100)
#define T2CON_TMR2ON_MASK (1<<2)
void Init_PIC(void)
{
// Diable all interrupts
INTCON = 0;
PIE1 = 0;
OPTION_REG = 0b11111111;
//Turn off comparitors
CMCON = 0b00000111;
//Set output default low:
PORTA = 0;
PORTB = 0;
//Port A Data Direction
TRISA = 0b00000000;
//Port B Data Direction
TRISB = 0b00000000;
}
//
// Setup CCP1 output for PWM at 5KHz
//
void Init_PWM(void)
{
T2CON = 0; // Stop TIMER2
PR2 = ((_XTAL_FREQ/4)/5000)-1; // Set for 5KHz PWM
CCP1CON = 0; // Stop PWM
CCPR1L = 0; // Set duty cycle to 0%
CCPR1H = 0;
CCP1CON = CCP1_CCP1M_PWM_MODE; // Select PWM mode
T2CON = T2CON_TMR2ON_MASK; // Turn on TIMER2
}
//
// Setup TIMER0 to assert T0IF every 4096 instruction clock cycles
//
void Init_TIMER0(void)
{
TMR0 = 0;
// TIMER0 clock source is the internal instruction cycle clock (_XTAL_FREQ/4)
// PRESCALER assigned to TIMER0
// PRESCALE set to 1:16
OPTION_REG &= 0b11010000;
OPTION_REG |= 0b00000011;
INTCON &= ~INTCON_T0IF_MASK;
}
void main(void)
{
unsigned char FadeDirection;
Init_PIC();
Init_PWM();
Init_TIMER0();
FadeDirection = 1;
for(;;)
{
if (INTCON & INTCON_T0IF_MASK)
{
INTCON &= ~INTCON_T0IF_MASK;
if (CCPR1L >= PR2)
{
FadeDirection = (unsigned char)(0-FadeDirection);
}
CCPR1L += FadeDirection;
}
}
}
Hi,
Don´t run lengthy loops within an ISR.
Without textual description and without knowing about your interrrupt interval timing, and the dimming timing...I don´t want to go deeper into your code.
Don´t make it unnecessary difficult for us to help.
Klaus
Give this code a try:
I tried to write this code to be as portable as possible between XC8 and MikroC.Code:/* * File: main_xc8.c * Target: PIC16F628A * Compiler: XC8 v1.45 * * Description: * Use the PWM output to fade an LED on and off. * * PIC16F628A * +----------:_:----------+ * <> 1 : RA2 RA1 : 18 <> * <> 2 : RA3 RA0 : 17 <> * <> 3 : RA4(*) OSC1/RA7 : 16 <> * VPP -> 4 : RA5/VPP OSC2/RA6 : 15 <> * GND -> 5 : VSS VDD : 14 <- 5v0 * <> 6 : RB0 PGD/RB7 : 13 <> PGD * <> 7 : RB1/RX/DT PGC/RB6 : 12 <> PGC * <> 8 : RB2/RX/CK RB5 : 11 <> * LED <- 9 : RB3/CCP1 PGM/RB4 : 10 <> * +-----------------------: * DIP-18 * Notes: * (*) RA4 is an open drain output. Requires an external pull-up for output. */ #include <xc.h> // PIC16F628A Configuration Bit Settings // CONFIG #pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD) #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD enabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #define _XTAL_FREQ 4000000ul #define INTCON_T0IF_MASK (1<<2) #define CCP1_CCP1M_PWM_MODE (0b1100) #define T2CON_TMR2ON_MASK (1<<2) void Init_PIC(void) { // Diable all interrupts INTCON = 0; PIE1 = 0; OPTION_REG = 0b11111111; //Turn off comparitors CMCON = 0b00000111; //Set output default low: PORTA = 0; PORTB = 0; //Port A Data Direction TRISA = 0b00000000; //Port B Data Direction TRISB = 0b00000000; } // // Setup CCP1 output for PWM at 5KHz // void Init_PWM(void) { T2CON = 0; // Stop TIMER2 PR2 = ((_XTAL_FREQ/4)/5000)-1; // Set for 5KHz PWM CCP1CON = 0; // Stop PWM CCPR1L = 0; // Set duty cycle to 0% CCPR1H = 0; CCP1CON = CCP1_CCP1M_PWM_MODE; // Select PWM mode T2CON = T2CON_TMR2ON_MASK; // Turn on TIMER2 } // // Setup TIMER0 to assert T0IF every 4096 instruction clock cycles // void Init_TIMER0(void) { TMR0 = 0; // TIMER0 clock source is the internal instruction cycle clock (_XTAL_FREQ/4) // PRESCALER assigned to TIMER0 // PRESCALE set to 1:16 OPTION_REG &= 0b11010000; OPTION_REG |= 0b00000011; INTCON &= ~INTCON_T0IF_MASK; } void main(void) { unsigned char FadeDirection; Init_PIC(); Init_PWM(); Init_TIMER0(); FadeDirection = 1; for(;;) { if (INTCON & INTCON_T0IF_MASK) { INTCON &= ~INTCON_T0IF_MASK; if (CCPR1L >= PR2) { FadeDirection = (unsigned char)(0-FadeDirection); } CCPR1L += FadeDirection; } } }
All you should need to do is delete the #include <xc.h> and #pragma statements.
if (CCPR1L >= PR2)
if ((CCPR1L < 1) || (CCPR1L >= PR2))
Syedhamzahasan - please don't suggest changing the product to solve the problem. If you think Arduino can replace a PIC, I challenge you to make an Arduino version of some of my PIC projects that use over 1Mb of memory and have to run at 64MHz. PIC is no better than Arduino, Arduino is no better than PIC but each has their own strengths and weaknesses, you have to respect that.
Brian.
Hi, Brian, thanks for your guide.XC8.h is propriety information from Microchip but it's free to download as part of the XC8 compiler package (currently v1.45). However, what Dan1138 is suggesting is you can easily convert it to MikroC format. The XC8.h is just a cross reference list of port names and numbers and bit names and numbers. An equivalent must exist for MikroC so if you can substitute it the program should compile. If you can't find it's equivalent, the real XC8.h file will probably work if you download it.
Things to remember:
1. The PWM can be set to maximum for full brightness and minimum for 'off'.
2. The PWM generator is a hardware device, once you configure it, the PWM comes out and stays running unless you reset or configure it again.
3. Use a spare timer to generate long delays for "1st Mode and 2nd Mode", alternating between maximum and minimum to blink the LED.
4. For "3rd Mode" use each delay to step up to maximum PWM then down to minimum again in a loop. At each 'tick' you reconfigure the PWM for the next brightness step.
Brian.
There is a bug in my code.
This line:
Should be replaced with this line:Code:if (CCPR1L >= PR2)
Code:if ((CCPR1L < 1) || (CCPR1L >= PR2))
I see solutions have already been provided. Although you should use arduino for fading. Its way easy to use than Pic MCU and you can use built in LED to observe the blinking and fading of LED in real time. It takes no time in getting programmed again and again.
Good Luck!
Syedhamzahasan - please don't suggest changing the product to solve the problem. If you think Arduino can replace a PIC, I challenge you to make an Arduino version of some of my PIC projects that use over 1Mb of memory and have to run at 64MHz. PIC is no better than Arduino, Arduino is no better than PIC but each has their own strengths and weaknesses, you have to respect that.
Brian.
I think every microcontroller easily can handle this. It is a personal taste to work with timer interrupts or not.Seems like you have a lot of experience in PIC, do you mind to tell me if I want to use PIC to use multiple output to control device individually?
For example, 4 output LED that switch ON individually base on 4 sensor. In this case is it i need to use timer interrupt to scan all 4 inputs?
I've been using them since the General Instruments PIC1650 came out over 30 years ago. It was a forerunner of the first Microchip ICs with an almost identical processor core and instruction set. The first project was for industrial lighting control where a simple switch could control many distributed high power lights (1KW each) distributed across huge factories and warehouses where a single switch would be incapable of handling the power and surge sequencing.Hi, Brian, thank you very much for your guidance.
Seems like you have a lot of experience in PIC, do you mind to tell me if I want to use PIC to use multiple output to control device individually?
Hi,
I think every microcontroller easily can handle this. It is a personal taste to work with timer interrupts or not.
My taste: I'd definitely use timer interrupts. A couple additiinal lines of code to set up the timer. But then it gives flexibility, deterministic results, exact timing (independent of how many channels are fading) ...
I'm working on an 8 channel light controller. Each channel with independent dimming, individual dimming-time-constant, individual value-to-brightness-curve, all in an 20ms loop, additionally a lot of communication (traffic) via two interfaces...
All on an AVR chip.
Klaus
I've been using them since the General Instruments PIC1650 came out over 30 years ago. It was a forerunner of the first Microchip ICs with an almost identical processor core and instruction set. The first project was for industrial lighting control where a simple switch could control many distributed high power lights (1KW each) distributed across huge factories and warehouses where a single switch would be incapable of handling the power and surge sequencing.
As Klaus points out, almost all MCU have the ability to sense and produce several signals to the outside World and apparently simultaneously although they really only do one task at a time very quickly. The way I do it with PICs is to use a timer to generate interrupts, this put the timekeeping in the 'background' while the rest of the program carries on. In the timer interrupt routine (the ISR) I check if variables are zero or not and if they are above zero, I decrement them. This means each of the variables counts down from your desired starting value to zero then stops. To start a timer, just write a value to the variable, to see if the delay period has ended, just check if the variable is zero. You can run as many variables at the same time as you wish and they all work independently but count down at the same speed. For example, if you make the timer interrupt period 0.1 seconds, then load 25 into a counter variable, it will reach zero in 2.5 seconds. If at any time you wrote 83 to another variable, it would reach zero 8.3 seconds later and there would be no interaction between the two delays.
Brian.
There is a flip-flop at every output.PIC output is not latched.
Hi,
There is a flip-flop at every output.
The software may switch the output to ON or OFF.
You may control as much outputs as you want independently. And you may read and process as many inputs as you like, independently.
Nothing special... done in almost any application.
I´m not familiar with PIC, but I assume there are instructions to modify a single bit of an output port. If not then keep the last wirtten value in SRAM and modifiy just the single bit you like using AND and OR instructions. For sure you write the complete byte, but only the bit_of_interest is modified.
Instead of keeping the last written value in SRAM you may RMW instructions or RMW functions.
Klaus
Indeed there are instructions. PIC devices have orthogonal instruction sets, the same instruction can be applied to any register, regardless of whether it is a memory or a port address. They don't have specific port bit instructions (in... out...) like some other MCU, you just set or reset a bit at the ports address.
Alpha91 - Once set, a bit remains set until you reset it. Your code turns it on, your code turns it off, it doesn't turn itself off when you move to the next instruction.
Brian.
Afaik this is the same with every microcontroller.so you mean even like PIC 16F628A or any other common PIC also same? the output remains until my code change it's state?
Hi,
Afaik this is the same with every microcontroller.
A quick view into a datasheet will give you this information.
Klaus
I think Klaus is correct.Afaik this is the same with every microcontroller.
I think Klaus is correct.
For example:
PORTA |= 0x01; will OR the current port A value with 00000001 which turns the least significant bit ON.
PORTA &= 0xFE; will AND the current port A value with 11111110 which turns the least significant bit OFF.
it stays that way until another instruction changes it.
Beware of RMW (Read Modify Write) problems with 10F, 12F and 16F series PICs if you copy my examples because the state of all the port pins is read in before writing the new value back. That isn't necessarily the same as reading back what you last wrote to the port - it is the present logic level it reads which might depend on external factors. A better method is to keep a copy of the port value in memory, modify it then write all the bits back to the port at once. On 18F series PICs, you don't have to do that but you should write output values to the LAT registers instead of the port.
Brian.
alright. sorry, i have one more question.
if my output require something like blink, like 500ms interval. so i need another timer for the blink? while i still want other output to work independently.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?