Why won't this PIC code light up my LEDs? - c

The following code won't set any of the pins high on my PIC18F14K50, yet it couldn't be simpler!
#include <pic18.h>
#include <htc.h>
void main(void)
{
// Set ALL pins to output:
TRISA = 0;
TRISB = 0;
TRISC = 0;
// Set ALL pins to high:
LATA = 0b11111111;
LATB = 0b11111111;
LATC = 0b11111111;
// Leave pins high and wait forever:
while (1);
}
I'm using MPLAB v8.43 and the Hi-Tech ANSI C Compiler.
A logic probe shows none of the pins high except the VUSB and the MCLR.
Any ideas?

At least some of the pins may be configured as Analog Inputs.
From the Datasheet for this device
The operation of pin RA4 as analog is selected by setting the ANS3
bit in the ANSEL register which is the default set-ting after a
Power-on Reset.
If you do not set the ANSEL register the pin cannot be used as output as it is configured as an analog input.
This applies to all the pins that can be A/D inputs, which does not cover all the pins you have.
Then again I do not see any configuration bit setup in your code. That device e.g. has 2 different instruction sets and you have to at the very least specify which instruction set you are using in the configuration bits.
You may try adding this to the top of your code just after the includes :
// Configuration BITS setup
__CONFIG(1, FOSC_INTIO2 & XINST_OFF);
__CONFIG(2, WDTEN_OFF & PWRTEN_ON);
__CONFIG(3, MCLRE_OFF);

I suppose that you didn't configure the MCPU oscillator, try to define:
; Oscillator:
config FOSC = INTIO2 ;Internal RC oscillator
;
; PLL x4 Enable bit:
config PLLCFG = OFF
and
;Define oscillator frequency
;{
movlw b'01100000'
movwf OSCCON
movlw b'01000000'
movwf OSCTUNE
;};
This directives are for MPLAB asm and not for Hi-Tech, but file registers should have the same names.

Related

Turning LED on in Nucleo 64 F103RB via Registers

I have a STM32 NUCLEO-64 F103RB and I am using Keil uVision 5. I was just testing the device with CubeMX software and was able to blink or turn on the green LED in my device. I then decided to do the same by changing the values in the registers on the board in C code directly. This is an schematic of the device:
Where I have highlited the GPIO A and the Bus that connects to the referred port. According to my understanding, two things should be done before actually turning the LED on:
1 - Activating the clock for the APB2 bus
2 - Setting the GPIOA Port 5 (which corresponds to the LED) to output mode.
I have done these two steps. However, the LED still won't turn on. I've tried looking at the documentation and found that the PA5 could be used as SPI, and I tried to change the register AFIO_MAPR (Page 184 of the reference manual) but that also didn't work. I tried looking at the clock activation for AHB2, but I didn't quite understand how it would work.
My C code is:
#include "stm32f10x.h" // Device header
int main() {
// Initialise clock of APB2 Bus
RCC->APB2ENR = (RCC->APB2ENR & 0x0) | RCC_APB2ENR_IOPAEN;
// Put the GPIOA in Output mode
GPIOA->CRL = (GPIOA->CRL & 0x44444444) | GPIO_CRL_MODE5_1;
// Changinging the ODR Register (Lighting the LED)
while(1) {
GPIOA->ODR = (GPIOA->ODR & 0x0) | GPIO_ODR_ODR5;
}
}
Nucleo64 F103RB Reference Manual
Nucleo64 F103RB User Manual
What step?
Enable GPIOA clock.
Configure pin to be push-pull output.
Toggle the pin.
For general GPIO do not set any AFIOs.
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
__DSB();
GPIOA -> CRL &= ~GPIO_CRL_CNF5_Msk;
GPIOA -> CRL |= GPIO_CRL_MODE5_Msk;
while(1)
{
GPIOA -> ODR ^= GPIO_ODR_ODR5;
for(volatile unsigned x = 0; x < 500000; x++);
}
you need also to check the solder bridges on the board:

How to properly configure the USART_BRR register in STM32L476RG uC?

I'm trying to write my own driver for USART_TX on an STM32L476RG Nucleo Board.
Here the datasheet and the reference manual.
I'm using Keil uVision 5 and I set in the Manage dialog:
CMSIS > Core
Device > Startup
Xtal=16MHz
I want to create a single character transmitter. According to the manual instructions in Sec. 40 p 1332 I wrote this code:
// APB1 connects USART2
// The USART2 EN bit on APB1ENR1 is the 17th
// See alternate functions pins and label for USART2_TX! PA2 is the pin and AF7 (AFRL register) is the function to be set
#include "stm32l4xx.h" // Device header
#define MASK(x) ((uint32_t) (1<<(x)));
void USART2_Init(void);
void USART2_Wr(int ch);
void delayMs(int delay);
int main(void){
USART2_Init();
while(1){
USART2_Wr('A');
delayMs(100);
}
}
void USART2_Init(void){
RCC->APB1ENR1 |= MASK(17); // Enable USART2 on APB1
// we know that the pin that permits the USART2_TX is the PA2, so...
RCC->AHB2ENR |= MASK(0); // enable GPIOA
// Now, in GPIOA 2 put the AF7, which can be set by placing AF7=0111 in AFSEL2 (pin2 selected)
// AFR[0] refers to GPIOA_AFRL register
// Remember: each pin asks for 4 bits to define the alternate functions. see pg. 87
// of the datasheet
GPIOA->AFR[0] |= 0x700;
GPIOA->MODER &= ~MASK(4);// now ... we set the PA2 directly with moder as alternate function "10"
// USART Features -----------
//USART2->CR1 |=MASK(15); //OVER8=1
USART2->BRR = 0x683; //USARTDIV=16Mhz/9600?
//USART2->BRR = 0x1A1; //This one works!!!
USART2->CR1 |=MASK(0); //UE
USART2->CR1 |=MASK(3); //TE
}
void USART2_Wr(int ch){
//wait when TX buffer is empty
while(!(USART2->ISR & 0x80)) {} //when data is transfered in the register the ISR goes 0x80.
//then we lock the procedure in a while loop until it happens
USART2->TDR =(ch & 0xFF);
}
void delayMs(int delay){
int i;
for (; delay>0; delay--){
for (i=0; i<3195; i++);
}
}
Now, the problem:
The system works, but not properly. I mean: if I use RealTerm at 9600 baud-rate, as configured by 0x683 in USART_BRR reg, it shows me wrong char but if I set 2400 as baud rate on real term it works!
To extract the 0x683 in USART_BRR reg i referred to Sec. 40.5.4 USART baud rate generation and it says that if OVER8=0 the USARTDIV=BRR. In my case, USARTDIV=16MHz/9600=1667d=683h.
I think that the problem lies in this code row:
USART2->BRR = 0x683; //USARTDIV=16Mhz/9600?
because if I replace it as
USART2->BRR = 0x1A1; //USARTDIV=16Mhz/9600?
THe system works at 9600 baud rate.
What's wrong in my code or in the USARTDIV computation understanding?
Thank you in advance for your support.
Sincerely,
GM
The default clock source for the USART is PCLK1 (figure 15) PCLK1 is SYSCLK / AHB_PRESC / AHB1_PRESC. If 0x1A1 results in a baud rate of 9600, that suggests PCLK1 = 4MHz.
4MHz happens to be the default frequency of your processor (and PCLK1) at start-up when running from the internal MSI RC oscillator. So the most likely explanation is that you have not configured the clock tree, and are not running from the 16MHz HSE as you believe.
Either configure your clock tree to use the 16MHz source, or perform your calculations on the MSI frequency. The MSI precision is just about good enough over normal temperature range to maintain a sufficiently accurate baud rate, but it is not ideal.

Why this simple PWM doesn't work in xc8

I know there are a lot of examples in internet, but what does need this code to work ?
frecuency oscillator = 4mhz
periode = 0.25us
duty_cicle = 250
Prescale = 16
PR2 = 124
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <pic16f88.h>
#pragma config FOSC = HS // 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 disabled)
#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 = ON // 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)
void main ()
{
while (1)
{
CCP1CON = 0x2C; /*activate PWM mode*/
PR2 = 0x7C; /*124 (DECIMAL)*/
T2CON = 0X06; /*prescale 16 */
CCPR1L = 0X3E;
}
}
I want to see :
Period of PWM = 2ms
Dutycicle = 1ms
Sincerilly
NIN
First off topic:
Don't include pic16f88.h, it's included by xc.h.
Little more off topic:
If you use a more modern part (e.g. PIC16f1619), you can use the MPLAB Code Configurator to generate the TMR2 and CCP code for you. It'll also cost less and have more flash/ram. That device is on the curiosity board ($20).
On Topic:
Your first stop is the datasheet.
The PWM section has the setup for PWM operation.
Step1:
The timer 2 takes Fosc/4 as an input, which is 1mhz in your case.
Target frequency is 500Hz. 1e6/500 = 2k.
I'd suggest a prescaler of 16, and pr value of 125. This will give you exactly 500Hz.
Step2:
We want a 50% duty cycle. CCP1L floor(125/2) = 62. CCP1X:CCP1Y = 0.5 * 4 = 2.
Step 3:
Clear the tris bit.
Step4 and 5:
Turn it on
// Step 1
TMR2ON = 0;
TOUTPS = 0;
T2CKPS = 2;
PR2 = 250U;
// Step 2
CCP1L = 62U;
CCP1X = 1;
CCP1Y = 0;
// Step 3
TRISB3 = 0;
// Step 4
TMR2ON = 1;
// Step 5
CCP1M = 0xC;
Hope that helps.
The datasheet states:
In Pulse-Width Modulation (PWM) mode, the CCP1 pin
produces up to a 10-bit resolution PWM output. Since
the CCP1 pin is multiplexed with the PORTB data latch,
the TRISB bit must be cleared to make the CCP1
pin an output.
So you must set the TRIS bit for the CCP1 pin to output:
TRISB &= ~(1 << 3); //Clear bit RB3/CCP1 in TRISB, makes PORTB3/CCP1 output.
This assumes CCPMX: CCP1 Pin Selection bit in the configuration word is clear. If set, then CCP1 is on RB0 in stead of RB3 but since I see no mention of CCPMX in your configuration pragma's i assume it is cleared.

PIC16F887 PORT won't work with XC8 C compiler

I'm pretty new to PIC programming and I'm trying to use C (compiled with Microchip's XC8 Free in MPLABX) to make a simple "Input to Output" program.
The problem I'm having is that the RA2, RA3 and RA5 input pins are just not working when programming in C.
It's probably not a hardware problem, because when programming in Ladder those pins work just fine.
I've searched around on the internet for a while and couldn't find anyone with the same problem yet.
The program I'm trying to burn onto the PIC is as follows:
#define _XTAL_FREQ 20000000
#include <xc.h>
// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = ON // Watchdog Timer Enable bit (WDT enabled)
#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)
//END CONFIG
int main()
{
TRISB = 0x00;
TRISE = 0x00;
TRISC = 0x00;
TRISD = 0xFF;
TRISA = \
_TRISA_TRISA2_MASK |\
_TRISA_TRISA3_MASK |\
_TRISA_TRISA4_MASK |\
_TRISA_TRISA5_MASK;
PORTD = 0x00;
PORTA = 0x00;
PORTB = 0x00;
PORTE = 0x00;
PORTC = 0x00;
while(1){
PORTB = PORTA;
}
return 0;
}
I do get an output on PORTB if I set RA4 to HIGH, but not for RA2, RA3 nor RA5. I believe this might be a problem with the configuration bits or something, but I'm not sure.
Hardware being used:
Microchip PIC16F887
FLEXiS Plus Board (sorry no english manual, but in page 8 and 9 there are board schematics)
Software being used:
Microchip MPLABX IDE
TinyBootloader
I think the problem is that those specific pins are also Analog Inputs for the ADC Module, you have to configure them to be digital I/O to use them. Try setting ANSEL = 0x00 at the beginning of your program.
You can see in the datasheet that the default value of ANSEL on POR is 0xFF so all analog pins are configured as analog inputs by default.
To use pins for analog input, you should set the relevant bits in both the ANSEL and TRISx registers.

PIC12 TRIS Register not setting

I'm trying to program a PIC12C508A to do a simple LED learning circuit. I've read some examples, the Microchip Datasheet, pic12c508a.h and pic12c508a.inc. I've tried to set the TRIS register using a C program and an ASM program but it does not take. Using MPLAB X, the XC8 compiler, and the built in simulator to check the SFR registers I can see that the TRIS is not updating even when the WREG holds the correct values. If anyone has experience with this please check out my code and see if I am doing something wrong.
#include <xc.h>
// -- CONFIG
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config WDT = OFF // Turn Watchdog Timer Off.
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#pragma config OSC = IntRC // Internal RC Oscillator
// -- Internal Frequency
#define _XTAL_FREQ 400000
int main()
{
TRIS = 0b111010; // 0x3A
//---0-0 Set GP0 and GP2 as outputs
GPIO = 0b000100; // 0x04
//---1-0 Set GP2 as HIGH and GP0 as LOW
for(int countdown = 10; countdown > 0; --countdown) {
__delay_ms(60000); // Delay 1 minute.
}
GPIO = 0b000001; // 0x01
//---0-1 Set GP2 as LOW and GP0 as HIGH
while(1)
NOP();
}
I also tried it an assembly which is pretty much identical to the Gooligum tutorials for baseline PIC models.
list p=12c508a
#include <p12c508a.inc>
__CONFIG _MCLRE_ON & _CP_OFF & _WDT_OFF & _IntRC_OSC
RCCAL CODE 0x0FF ; Processor Reset Vector
res 1 ; Hold internal RC cal value, as a movlw k
RESET CODE 0x000 ; RESET VECTOR
movwf OSCCAL ; Factory Calibration
start
movlw b'111010' ; Configure GP0/GP2 as outputs
tris GPIO ;
movlw b'000100' ; Set GP2 HIGH - GREEN LED
movwf GPIO
goto $ ; loop forever
END
This all seems pretty straight forward but when I use breakpoints and examine the SFR registers in the simulator I can see that the GPIO and TRIS registers never are changed even though the WREG will hold the correct values. I've examined the ASM output that the XC8 compiler generates and it is almost identical to the ASM I wrote when it comes to setting the registers.
I've also tried using HEX values and straight integer values and the results are the same.
The answer is that the crystal frequency defined at the top of the program was way beyond the real actual value
#define _XTAL_FREQ 400000 //that's 400KHz INTOSC, impossible
Instead it should be
#define _XTAL_FREQ 4000000 //That's 4MHz INTOSC
#Justin pointed it out in the comment below it's original post.
First, in order to use GP2 as an output, do you need to clear the T0CS in the OPTION register ?
Second, I observe this in the manual:
Note: A read of the ports reads the pins, not the output data latches.
That is, if an output driver on a pin is enabled and driven high, but
the external system is holding it low, a read of the port will
indicate that the pin is low.
but I guess the simulator will assume the external system is not holding down the pin.
Third, BCF and BSF instructions look like a better way of waggling GP2 and GP0 independent of whatever else is going on in the GPIO.
I'm sorry, but other than that I don't know what to suggest.
You can try different GPIO, because according to the documentation, GP2 may be controlled by the option register.

Resources