I am trying to understand how to attach external falling edge interrupt to a dsPIC33EP512MU810 micro controller. From browsing the internet I have found the following code:
RPINR0= 0x5400;//set pin 1 as interrupt 1
INTCON2 = 0x0000; /*Setup INT0, INT1, INT2, interrupt on falling edge*/
IFS1bits.INT1IF = 0; /*Reset INT1 interrupt flag */
IEC1bits.INT1IE = 1; /*Enable INT1 Interrupt Service Routine */
IPC5bits.INT1IP = 4; /*set low priority*/
I am trying to understand how to attach this interrupt to A10. What address should I pass to the RPINR0? And which pins can be used for such interrupt?
RPINR0 requires the RP-Pin number (you can look in the datasheet next to the pin). E.g. if you wanted to use Pin E5 it reads: AN29/PWM3H/PMD5/RP85/RE5 - meaning its remappable pin 85. So
PRINR0bits.INT1R = 85;
would work.
However for pin A10 it reads: VREF+/RA10 - meaning A10 is not available as a remappable In-/Outport.
Sry, you will have to choose another pin.
Kind Regards,
David
Related
I am using a STM32F415RGT6 embedded in the 1Bitsy Board. I want to set up the I2C Peripheral in order to read some data from a sensor. I am using the stm32f4 standard peripheral library.
My example code:
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitTypeDef gpioInit;
GPIO_StructInit(&gpioInit);
gpioInit.GPIO_Mode = GPIO_Mode_AF;
gpioInit.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
gpioInit.GPIO_PuPd = GPIO_PuPd_UP;
gpioInit.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
GPIO_Init(GPIOB, &gpioInit);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_DeInit(I2C1);
I2C_InitTypeDef I2C_InitStructure;
I2C_StructInit(&I2C_InitStructure);
/* I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x01;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd(I2C1, ENABLE);
while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
/* Generate Start, send the address and wait for ACK */
I2C_GenerateSTART(I2C1, ENABLE);
while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1, 0xE0, I2C_Direction_Transmitter);
while (!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
After that I want to write a 0x00, but the code always hangs in the last line, apparently the Master never reads the acknowledge. The I2C status registers always read:
I2C1 -> SR1 = 1024
I2C1 -> SR2 = 3
which means that the Acknowledge Failure bit is always set. If I analyze it using my Saleae I get the following:
The Slave sends the ACK, but the STM32F415 cannot read it.
The weird thing: If I try the same code on my F407 - Disco (only with clock set to 400khz, but it's the same behaviour on both MCUs regardless of Speed), it works flawlessly:
All other peripherals work fine. I already tried several workarounds, but the AF bit is always set, regardless of method. I hope you can help me.
P.S: I have tried with and without additional pullups and the I2C Slave Address is fine, because it works with STM32F0, STM32F4-DISCO and Atmel Mcus.
Best Regards and Thanks in advance!
I'm trying to program an atmega328p, but the SPI bus isn't working. It's not sending any data over the bus.
My code is as follows:
#include <asf.h>
#include <stdio.h>
#include <main.h>
int main (void)
{
board_init();
SPI_MasterInit();
DDRD = (1<<DDD5);
while(1)
{
PORTB &= ~(1<<DDB2);
SPI_MasterTransmit(0xAB);
PORTB |= (1<<DDB2);
PORTD ^= (1<<DDD5);
}
}
void SPI_MasterInit(void)
{
/* Set MOSI and SCK output, all others input */
DDRB = (1<<5) || (1<<3) || (1<<2);
/* Enable SPI, Master, set clock rate fck/16 */
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}
void SPI_MasterTransmit(char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)));
}
I'm trying to send some random data over the bus (0xAB) to check if the bus works properly so I can add further code. In the while loop I also set a pin.
On my scope image I see no data being send on the SPI pin MOSI and the CLK pin is also not sending information. PB5 (the pin I'm inverting everytime I try to send data) is working and has a period of about 20 microseconds.
I'm programming the Atmega328p through an Atmel ICE. The programming interface is also through SPI, I read somewhere that this might be an issue. I'm not completely sure.
Does anyone know what might be the problem?
My first guess was not setting SS pin (PB2) as output. It may cause switching to the slave mode almost randomly. But it seems to be set as an output (it's not stated in comments).
But after closer look to this expression, it's obvious it's not set at all:
DDRB = (1<<5) || (1<<3) || (1<<2);
There is a huge difference between logical or || and bitwise or |.
Examples of writing to a port seem to always use the port number as a constant, eg,
OCR2A = 180;
How do you write to the port when the port is unknown until run time. For example,
int port = (buttonPressed) ? 0x3b : 0x3c;
portWrite( port, 180 );
What I cannot find is the funtion portWrite(). Does something like that exist?
Robert's answer has some imprecise assertions and an incomplete answer.
Writing directly to port registers you can ruin other settings of the port and sometimes cause permanent damage to controller.
Can ruin other settings: true, you have to know what you are doing (for instance what pins are on the port you are manipulating, and know what are the functions you want to keep.
Can cause permanent damage: not really, or better not because of the port manipulation. If you wire a short circuit to ground and then set it as an output to 1, you can damage it whether you are using the port register or the digitalwrite. You have to be careful in both ways.
Now, returning to your problem, the enumeration is one way, but since the PORTB, PORTC, PORTD are just short name for values, you can set a variable and then use it to indirectly access it.
The type for this kind of variable is a volatile pointer to a byte (volatile means that write and read operations cannot be optimized by the compiler, since the value can change even between two operations):
volatile uint8_t *variablePortRegister;
You just have to load it with the address (so with the & symbol) of the register you want to change:
variablePortRegister = &PORTC;
then use the pointer to change the value
PORTC = 0x12;
becomes
(*variablePortRegister) = 0x12;
This is a short example. For it to work, connect a LED with resistor on arduino pin 5 (bit 5 of PORTD). The LED on the board (labeled L) is connected to pin 13 (bit 5 of PORTB).
The sketch will make one of the two leds blink for five times, then switch to the other. Only port manipulation instructions are used, and you can find that the way to read the port is the same as the one to write it.
volatile uint8_t *myportreg;
unsigned long lastTime;
uint8_t counter;
void setup() {
DDRB |= 0x20;
DDRD |= 0x20;
PORTB = 0;
PORTD = 0;
counter = 99; // trigger the register change immediately
}
void loop() {
if (counter >= 10)
{
counter = 0;
if (myportreg == &PORTD)
myportreg = &PORTB;
else
myportreg = &PORTD;
}
if ((millis() - lastTime) > 500)
{
lastTime = millis();
// change bit 5 of register
*myportreg = 0x20 ^ (*myportreg);
counter++;
}
}
EDIT: as Robert pointed out, it's much better to "use" just the pins you need (in this case, bit 5 of port B and D) rather than setting the whole port; this way you minimize the risk of screwing up something else. This edit is already included in the above code, so the code is correct
The port is a bit in one particular register. If you know the register and the position of the port in that particular register you can try this:
register = (1<<port) || register
to set the port to 1 and
register = (1<<port)^-1 && register
to set the port to 0.
Of course, you will need a switch somewhere to determine the register and the bit of the port in the register given the port name.
When I try to receive the USART signal with my Silicon Labs CP210x USB to UART Bridge. The only thing I receive is:
<0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0><0> etc
I got the right settings selected: baud rate: 9600 data bits: 8 parity: none stop bits: 1
I use a ATmega128A3U. The test_LED (see code below) on port E pin 0 is working. I used a oscilloscope to check the uart signal. See picture here: http://imgur.com/dPxkdZ6
Does someone know a solution for this?
Does anyone know how to fix a framing error? (My UART software is giving this error)
CODE:
#define F_CPU (32000000UL) // CPU clock speed
#include <avr/io.h>
#include <util/delay.h>
void USARTF0_init() {
USARTF0_BAUDCTRLB = 0; //BSCALE is 0
USARTF0_BAUDCTRLA = 0xCF; //BSEL is 207
USARTF0_CTRLA = 0; //Disable interrupts
USARTF0_CTRLC = USART_CHSIZE_8BIT_gc; //8 data bits, no parity and 1 stop bit
USARTF0_CTRLB = USART_TXEN_bm | USART_RXEN_bm; // //Enable receive,transmit and high speed mode
PORTF_OUTSET = PIN3_bm; // Port F pin 3 as TX
PORTF_DIRSET = PIN3_bm; // TX pin as output
PORTF_OUTCLR = PIN2_bm; // Port F pin 2 as RX
PORTF_DIRCLR = PIN2_bm; // RX pin as input
}
void sendChar(char c) {
while( !(USARTF0_STATUS & USART_DREIF_bm) ); //Wait until DATA buffer is empty
USARTF0_DATA = c;
}
void sendString(char *text) {
while(*text) {
sendChar(*text++);
}
}
int main(void) {
USARTF0_init();
PORTE.DIRSET = PIN0_bm; // make port E pin 0 output (test_LED)
while(1)
{
_delay_ms(10);
sendString("Hello World!\n\r");
PORTE.OUTTGL = PIN0_bm; // test_LED Toggle
}
}
Code source: http://morf.lv/modules.php?name=tutorials&lasit=29
To recap the discussion, so it can useful to someone later.
If you have an oscilloscope, capture a trace for a simple test case, as #DrOctorooi has done with "#~00":
He has marked start and stop bits, and also the data bits (for serial/UART they're least-significant first)
This confirms that UART somehow works.
One should also confirm the voltage levels. 0-3.2V looks about right.
And the time base. On the captured trace it appears 1 bit takes 1.625ms, which means a baudrate of around 615. That's quite far from expected 9600. In fact, that's around 16 times slower.
Since the error has to do with time, the immediate questions are the MCU clock and UART clock dividers (and on more complex devices, and intermediate dividers and clocks).
It turns out the dividers were meant for the 32MHz clock, but this MCU has a clock of 2MHz when it comes out of reset (16 times slower, as we have seen above). Solution was to recalculate the dividers.
I need to transfer data serially from AT89s52 to Hyperterminal of PC.
For that I made a sample program to print "Hello" on the hyperterminal of my PC by programming the below given code inside 89s52 microcontroller and connecting it to my PC via serial port. Now when I am opening hyperterminal for the respective port, I should be seeing "Hello" printed on the screen multiple times, but what actually I am seeing is some garbage data getting printed.
This is the code I have used.
#include < AT89X52.H>
#include < STDLIB.H>
#include < STDIO.H>
unsigned int i;
void main (void)
{
TMOD = 0x20;
SCON = 0x50;
TH1 = 0xFD;
TL1 = 0xFD;
TR1 = 1;
TI = 1;
P1 = 0;
while (1)
{
puts("Hello\r");
P1 ^= 0x01; /* Toggle P1.0 each time we print */
for(i=0;i<25000;i++);
}
}
In the Hyper terminal I am not getting correct output i.e. Hello. Instead I am seeing some Garbage characters..
Can anybody help on this please..?
Can you See P1 is toggling? I would rather send a single character first and observe what is sending by using an oscilloscope. You should see a digital signal corresponding to the ASCII value of the character being split-out from the TX pin of the micro. Also you can check the baud rate (exact value) by using the scope. If you are convinced that the correct value is sent at the right baud rate it is most likely that you got a bad connection or perhaps the baud rate should slightly be changed.