The program is suppose to detect what switch is turned on and from there change the traffic light to either red, yellow, or green. I'm stuck and I don't know if my initialization are right for Port A and Port E. we are only suppose to change the DEN and DIR. When I run it on debug, nothing happens. It's supposed to start with the red light.
// Input/Output:
// PE2 - Red
// PE1 - Yellow
// PE0 - Green
// PA3 - South
// PA2 - West
// Preprocessor Directives
#include <stdint.h>
#include "tm4c123gh6pm.h"
// Global Variables
uint8_t In0, In1;
uint8_t Out;
// Function Prototypes - Each subroutine defined
void Delay(void);
int main(void) {
// Initialize GPIO on Ports A, E
unsigned long int delay;
SYSCTL_RCGC2_R |= 0x11; // enables clock for e and a
delay = SYSCTL_RCGC2_R;
GPIO_PORTE_AMSEL_R = 0x00; //diables analog
GPIO_PORTE_AFSEL_R = 0x00; //disable alternate function
GPIO_PORTE_PCTL_R = 0x00000000; //enable GPIO
GPIO_PORTE_DEN_R = 0x07; // Ports E0-2
GPIO_PORTE_DIR_R = 0x07; //inputs PE0-2
GPIO_PORTA_AMSEL_R = 0x00; //disables analog
GPIO_PORTA_AFSEL_R = 0x00; //disable alternate function
GPIO_PORTA_PCTL_R = 0x00000000; //enable GPIO
GPIO_PORTA_DEN_R = 0x0C; // Ports A2 and A3
GPIO_PORTA_DIR_R = ~0x0C; //outputs PA2 and PA3
// Initial state: Red LED lit
Out = (GPIO_PORTE_DATA_R & 0x04); //red starting
while(1) {
In0 = GPIO_PORTA_DATA_R&0x08 ; // Read value of south
In1 = GPIO_PORTA_DATA_R&0x04 ; // read west
// Check the following conditions and set Out appropriately:
// If south is enabled and red LED is on, then red LED turns off and green LED turns on.
// If west is enabled and green LED is on, then green LED turns off and yellow LED turns on.
// If yellow LED is on, then yellow LED turns off and red LED turns on.
if ((In0 == 0x08) & ((Out&0x04) == 0x04)){ // south and red
GPIO_PORTE_DATA_R = 0x01; //green light turns on
Delay();
Out = GPIO_PORTE_DATA_R;
}
if ((In1== 0x04) & ((Out&0x01) == 0x01)){ //west and green
GPIO_PORTE_DATA_R = 0x02; //yellow light turns on
Delay();
Out = GPIO_PORTE_DATA_R;
}
if ((Out&0x02) == 0x02){ //if yellow
GPIO_PORTE_DATA_R = 0x04; //red light turns on
Delay();
Out = GPIO_PORTE_DATA_R;
}
Out = GPIO_PORTE_DATA_R;
// ??? = Out; // Update LEDs based on new value of Out
}
}
// Subroutine to wait about 0.1 sec
// Inputs: None
// Outputs: None
// Notes: the Keil simulation runs slower than the real board
void Delay(void) {
volatile uint32_t time;
time = 727240*200/91; // 0.1sec
while(time) {
time--;
}
}
are you sure about the direct register modifications?, try to double check if you are flipping the correct bits in registers. Also check what these hex values you writing are correct. Take a multi-meter and measure the voltage on the mentioned GPIO, does it change as supposed?, if not then either your electric circuitry has bug, or the inits().
Related
My Problem is that I have a digital Input initialized on PORTB.0. On that Pin I have a button and a 100k Pull-down Resistor. When I run my Pic with literally nothing ( void main() {while(1){}} ) the Voltage level on this pin works as I want it to (0 to 3.3V). But after I test my programm and initialize as shown in the Code below, it's range goes from 2.8 to 3.3V.
I am using a PIC18LF2520 for my graduation work. I am Programming in MPlab V5.10 with the XC8 1.45 Compiler. I just want an Interrupt for my Button which lies on the RB0 Pin of the uP. The initialisations I made will be shown on the Code down below. I already worked a lot with this particular PIC, but I have never had such an Error before.
void main() {
init();
while(1) {
/*
if(isEXT0Set()) { //If the Button gets pushed
EXT0Int(); //Interrupt Function call
}
*/
}
}
void init() {
//PORT Definitions
TRISA = 0x00;
TRISB = 0xC3;
TRISC = 0x00;
//Oscillator Settings
OSCCON = 0x7F; //8Mhz; Internal Oscillator; INTOSC stable
//Interrupt Settings
INTCON = 0xF0; //Global Enable; Peripherals Enable; TMR0 Enable; INT0 Enable
INTCON2 = 0x64; //INT0 rising Edge; INT1 rising Edge; TMR0 High Priority
INTCON3 = 0x08; //INT1 Enable
ADCON1 = 0x0F; //set all Inputs to Digital ones.
//Timer Settings
T0CON = 0x86; //16-Bit; LtoH; 1/128
T1CON = 0x31; //2 8-Bit; FOSC/4; 1/8
T2CON = 0x07; //Postscaler 1/1; Prescaler 1/16;
TMR0H = 0xE1; //Setting TMR0 to 1 Second
TMR0L = 0x7B;
TMR1IE = 1;
TMR2IE = 0;
}
I expect that when I push the button that INt0IF will be set, but that doesn't happen. I testes it on the Hardware, the result is decribed up above. I hope someone sees what I missed. Thanks in advance. :D
PIC controller has internal pull-up resistors on PORTB and usually, they're much less than 100kOhm. You can turn all of them just changing INTCON2 initialization to:
INTCON2 = 0xE4;
I'm trying to write a simple program in C that turns a row of LED lights OFF when I press a button. I'm very new to both embedded devices and using bitwise operators and I can't figure out what I'm doing wrong.
I'm using a Romeo board with an Amega328p which is hooked up to an I/O kit board where the pins connect to the LEDs and push buttons seperately.
Romeo Schematic
I/O Tainer Board Schematic:
The pins have DDRx PORTx and PINx settings.
I've connected pins D2-D7 to JP3_1-6 for the LEDs (I can see this part works)
I've connected pin D10 (PB2) to JP2_5 for the button (problem part)
I've connect the GNDs & VCCs on both boards to each other.
Here is my code:
void main()
{
DDRD = 0b11111100; // open all registries to be used
PORTD = 0b11111100; // set all LEDs ON to start
DDRB = 0b00000000; // set as input
PORTB = 0b00000100; // set PB2 pull up resistors
if((PINB & 0b00000100)==0) // if buttons pressed
{
PORTD = 0b00000000; // turn all lights off
}
}
When I push the button nothing happens. I don't think it's the board because it doesn't matter what switch I use.
Any help or direction in solving this would be appreciated. I think it's code and not how I'm hooking things up but I'm a newbie so I could be wrong.
What is happening is that the if statement is ran once(probably before you even press the button), and then main returns. To fix this you need to run the if statement inside of a while loop. Something like:
void main()
{
DDRD = 0b11111100; // open all registries to be used
PORTD = 0b11111100; // set all LEDs ON to start
DDRB = 0b00000000; // set as input
PORTB = 0b00000100; // set PB2 pull up resistors
while(1)
{
if((PINB & 0b00000100)==0) // if buttons pressed
{
PORTD = 0b00000000; // turn all lights off
}
//TODO: set LEDs on button release?
}
}
I do not know what happens when main returns on your micro-controller. A common thing is for main to be re-ran.
I'm trying to using C on the Arduino board to control the speed of the 2 motors. However, when uploading the code, each motor runs at different speed despite having the same OCR value. Can you give it a check for the reasons, I would be very appreciate if you do so. The two motors is the same. The board I use is Arduino Uno
#include <avr/io.h>
#include <util/delay.h>
void setup() {
DDRB = B11111100;
DDRD = B00000000;
TCCR2A = TCCR1A = B10100011;
TCCR2B = B00000001;
TCCR1B = B00000100;
OCR2A = 0;
OCR1B = 0;
}
void loop() {
OCR1B = 255;
OCR2A = 255;
PORTB |= _BV(PORTB4);
PORTB |= _BV(PORTB5);
}
Timer 2 is 8 bit wide, but Timer 1 is 16 bit wide. The motor connected to the OCR1B output gets 255/65535=0.3% PWM, while OCR2A gives 255/255 = 100% PWM to the other motor.
You can
use the CTC (clear timer on compare match) mode
use two timers of the same width, like timer 0 and timer 2
use two output compare units of the same timer (e.g. OCR1A/OCR1B)
This question already has an answer here:
C8051f312 microcontroller [closed]
(1 answer)
Closed 9 years ago.
I have the 8051F312 microcontroller, and I have to turn on the led (on the 7.bit of the P2 port). My code is not working, maybe you have some ideas.
#include < C8051F310.H >
#include < stdio.h >
sbit LED_16 = P2^7; // P2^7-->green LED: 1 = ON; 0 = OFF
void init(void)
{
// XBRN registers_init
XBR1 = 0x40; // Enable the crossbar
PCA0MD &= 0X40; // Disable Watchdog
P2MDOUT |= 0xF0;
ADC0CN = 0x80;
ADC0CF = 0xFC;
REF0CN = 0x08;
}
void main(void)
{
init();
while (1)
{
LED_16 = 1; // LED continuously illuminated
}
}
(sorry for the format, but I had problem with the text editor)
First you need to set input/output to the GPIO. For 8051 micro controller family(According to my knowledge)(I don't know about 8051F312), assigning 1 to a pin sets that gpio as input and assigning 0 sets that gpio as output. So in your case first you need to set P2.7 as output. For that you need to do LED_16 = 0; in your init function. After that you need to consider how your LED is connected to your micro controller pin. If anode of LED connected to micro controller pin you need to make it HIGH to glow the LED. If cathode of LED connected to micro controller pin you need to make it LOW to glow the LED.
If anode of led connected to micro controller your code should be
void main(void)
{
init();
while (1)
{
LED_16 = 1; // LED continuously illuminated
}
}
If cathode of led connected to micro controller, then your code should be
void main(void)
{
init();
while (1)
{
LED_16 = 0; // LED continuously illuminated
}
}
Please find AN101 application note from Silicon Labs. I have compared example source code with your code and I have noticed that:
They use XBR2 = 0x40 for crossbar initialization.
They enable /SYSCLK by XBR1 = 0x80.
They configure output pin to push-pull mode by PRT1CF |= 0x40 (I think it should be PRT1CF |= 0x80 in your case).
I have written this program in mplab v8.63 with c compiler C18 on the pic 18F4550. if I press the button on my picdem (S3) and there is a led connected on RB5 (with a resistor) then the led goes on. When i pressed on (S3) and there is a led on RB4, the the led will not be on (while I expected this) the same with RB3. Thit I forgot something to set?
The goal is for the red, green and blue LED separately measured with a LDR. but first I obviously must enable the ports RB5, RB4 and RB3.
#pragma code
/******************************************************************************/
void main (void)
{
TRISD = 0x00; // PORTD as output
TRISB = 0b00110000; // RB4 en RB5 as input
TRISA = 0x00; // RA output
RCONbits.IPEN = 0; // priority
INTCONbits.GIE = 1; // enable interrupt
INTCONbits.RBIE = 1; // interrupt portB on
while(1)
{
_asm sleep _endasm
}
}
#pragma interrupt ISR
void ISR (void)
{
//int red= 01110010011011110110111101100100;
int on = 1;
int off = 0;
if (INTCONbits.RBIF==1)
{
if(PORTBbits.RB5==0) // S3 pressed?
{
LATDbits.LATD1 ^= 1; // D2 toggle
LATAbits.LATA2 ^= on;
}
if(PORTBbits.RB4==0)
{
LATDbits.LATD1 ^= 1; // D2 toggle
LATAbits.LATA2 ^= on;
}
if(PORTBbits.RB3==0)
{
LATDbits.LATD1 ^= 1; // D2 toggle
LATAbits.LATA2 ^= on;
}
}
INTCONbits.RBIF = 0;
}
In the PIC TRIS registers, a bit set to 1 means input and 0 means output. You set TRISB = 0b00110000 which is all outputs on port B apart from RB5 and 4 which are inputs. If you need RB3 as a digital input as well, you need to set TRISB = 0b00111000. The bits are counted b7,b6,b5,b4,b3,b2,b1,b0.
However, you are expecting RB3 to trigger the RBIF which it does not as I explained here. So as you have it, only RB5 and 4 would trigger RBIF, but if RB3 was low at that time it would toggle D1 and A2. So move this code to main loop as I suggested until you get it working, then make it work on interrupt.
As ChrisJ says, some pins default to analog input unless you disable it so you wont get the digital input and interrupt on pin change that you are expecting using ADCON1
If the PBADEN bit is set, PORTB is initialized with RB4:RB0 set as analog inputs. If so you must use ADCON1 to disable analog inputs on RB4:RB0. The example program at the beginning of Section 10.2 of the manual wites 0x0E to ADCON1 to properly initialize PORTB.
See also Section 21.0 for an explanation of ADCON1 bits.