why 0x40010800 + 0x0C equals 0x40010830? - embedded

I tried to access RCC_APB2ENR register as a first step to blink green led on stm32nucleo f103rb
then I added 0x0C to 0x40010800(RCC base address).
The expected result was 0x4001080C but the actual result was 0x40010830!!!
It seems 0x0C was left shifted twice but I can't understand why this thing happened.
And even in Ubuntu, the same thing happened.
please let me know
board : stm32 nucleo f103rb
IDE : uVision 5

RCC_BASE points to unsigned int. On your platform size of this type is 4 bytes.
While adding or subtraction to pointers you are increasing (or decreasing) address by operand multiplied by size of element.
For details looks Pointer Arithmetic

Related

how to drive a dotstar strip from C on a raspberry pi

I am trying to figure out how to drive a dotstart strip by calling write(handle, datap, len) to an SPI handle, from C, on a raspberry pi. I'm not quite clear on how to lay out the data.
Looking at https://cdn-shop.adafruit.com/datasheets/APA102.pdf#page=3 makes me think you start with 4 bytes of 0, a string of coded LED values (4 bytes per LED) and then 4 bytes of 1's. But that cannot be right; the final 4 bytes of 1's would be indistinguishable from a request to set an LED to full brightness white. So how could that terminate the data?
Insight welcome. Yes, I know there's a python library out there for this, but I'm coding in C++ or C.
After much digging, I found the answer here:
https://cpldcpu.wordpress.com/2014/11/30/understanding-the-apa102-superled/
The end frame is more complex than the spec suggests, but the spec is correct if your string has 32 LEDS, and you must always specify values for all LEDS in your string.

Reading incorrect temperature value from thermistor using EVK1100

I want to get the temperature from a thermistor, so I made a voltage divider (3.3V to 10k resistor and between ground a 10k thermistor) I read the ADC between the 10k resistor and the thermistor.
The BCOEFFICIENT is 3977, the NOMINAL TEMPERATURE is 25C and I use the simple B parameter equation. I'm not sure where I'm doing mistake, I read room temperature as 10.5C which was suppose to be around 24C. The following is the part of the program that I used for temperature sensor(developed in AVR studio),
#define TEMPERATURENOMINAL 25
#define TERMISTORNOMINAL 10000
#define BCOEFFICIENT 3977
#define SERIESRESISTOR 10000
{
float ke1,tempa,xin
ke1 = adc_get_value(peak_adc2,peak2);
xin=(1023/ke1)-1;
xin=SERIESRESISTOR/xin;
tempa=xin/TERMISTORNOMINAL;
tempa=log(tempa);
tempa/= BCOEFFICIENT;
tempa+=1.0/(TEMPERATURENOMINAL + 273.15);
tempa=1.0/tempa;
tempa-=273.15;
dip204_set_cursor_position(1,3);
//sprintf(ui, "Temp is %.2f deg", Ref);
sprintf(ui, "Temp is %.2f deg", tempa);
dip204_write_string(ui);
}
I checked the voltage using multi-meter for instance in between the thermistor and 10k resistor and in the EVK 1100 using the following line
ke1 = adc_get_value(peak_adc2,peak2)*3.3/1024;
I get the same voltage in both.
Not sure where I'm doing a mistake, Hope someone guide me in right direction
Your code looks correct to me, and I suspect a hardware problem may be the culprit.
It seems likely you have inadvertently connected two 10K-ohm pull-up resistors between the ADC input and the +3.3V reference: perhaps one is already populated on the EVK1100 board, and you have added another one externally connected to your thermistor. This would be equivalent to putting both 10K-ohm resistors in parallel with each other, which would be equivalent to a 5K-ohm resistor in series with the thermistor. At 25°C, the thermistor resistance Rt would read 10K ohms, which would produce a voltage of:
+3.3V * (Rt / (Rt + 5K))
= 2.20V
instead of the correct +1.65V. This number is very close to the result you are seeing (+2.17V # 24°C).
You can verify this hypothesis by looking at the schematic and/or PCB for the EVK1100 to see if a 10K-ohm pull-up resistor is connected from the ADC input to +3.3V. If this is the problem, remove one of the two resistors and you should see correct behavior.

how to perform floating point calculation in tmote sky (contiki)

I have the following code snippet:
#include "contiki.h"
#include <stdio.h> /* For printf() */
PROCESS(calc_process, "calc process");
AUTOSTART_PROCESSES(&calc_process);
PROCESS_THREAD(calc_process, ev, data)
{
double dec=13.2, res=0, div=3.2;
PROCESS_BEGIN();
res=dec+div;
printf("%f",res);
PROCESS_END();
}
After uploading the above code in Tmote sky platform using the command
make TARGET=sky calc.upload, the program will be loaded to the mote (there is no error). Then login to the mote using make login TARGET=sky, the following output is displayed....
OUPUT:
**Rime started with address 4.0
MAC 04:00:00:00:00:00:00:00 Contiki 2.7 started. Node id is set to 4.
CSMA ContikiMAC, channel check rate 8 Hz, radio channel 26
Starting 'calc process'
%f**
How can I get the correct value?
Thanks
It is not floating point calculation support that you need - you have that already. What is missing is floating point support within printf(). That is to say that res will be calculated correctly, but printf() does not support its display.
Because it requires a relatively large amount of code, many microcontroller targeted libraries omit floating point support in stdio. There may be a library build option to include floating point support - refer to the library documentation.
You might do well to ask a question about the specific calculation necessary, and how it might be done using integer or fixed point arithmetic. Alternatively you might write your own floating point display as described here: How to print floating point value using putchar? for example.

What happens when you send an 8bit number to an output which is 4bit? C Language

I'm studying in high school, and we have an electronics project.
We have an output from our computer which is 4 bit, output address is 37Ah
and my teacher did this:
outportb(0x37A,0x80);
so what will appear in the output? 0h or 8h?
Unless this is a 4-bit CPU from the 70s then your output port will be 8 bits, but the connected hardware might only use 4. In that case it is common (but not necessary) to use the lower 4 bits so you would have 0x0 as value. But that makes using 0x80 a smokescreen, it would be the same as 0x00 and 0xF0. So from that alone I would guess that the upper 4 bits are used here, and the value sent is 0x8.
But a twisted hardware engineer could have used the middle 4 bits.
You need to explain your problem a little better. What microprocesser do you use etc. Is it a 4-port output you have?
But 0x80 is equal to:
0b1000000 and if you use the lower 4 bits: 0b1000xxxx, then they will be zero (not turned on). This will happen if 0x37A is 8bit.
Otherwise, explain your problem better :)
Can't you try and see what happens? or is it only theoretical until now?
EDIT:
I see it is a printer port. Check http://www.tinet.cat/~sag/gifs/ParallelPort.gif if you use port 2,3,4,5 then the upper 4 bits really doesn't matter :) as said in my comment.

How I can fix this code to allow my AVR to talk over serial port?

I've been pulling my hair out lately trying to get an ATmega162 on my STK200 to talk to my computer over RS232. I checked and made sure that the STK200 contains a MAX202CPE chip.
I've configured the chip to use its internal 8MHz clock and divided it by 8.
I've tried to copy the code out of the data sheet (and made changes where the compiler complained), but to no avail.
My code is below, could someone please help me fix the problems that I'm having?
I've confirmed that my serial port works on other devices and is not faulty.
Thanks!
#include <avr/io.h>
#include <avr/iom162.h>
#define BAUDRATE 4800
void USART_Init(unsigned int baud)
{
UBRR0H = (unsigned char)(baud >> 8);
UBRR0L = (unsigned char)baud;
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << URSEL0) | (1 << USBS0) | (3 << UCSZ00);
}
void USART_Transmit(unsigned char data)
{
while(!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
unsigned char USART_Receive()
{
while(!(UCSR0A & (1 << RXC0)));
return UDR0;
}
int main()
{
USART_Init(BAUDRATE);
unsigned char data;
// all are 1, all as output
DDRB = 0xFF;
while(1)
{
data = USART_Receive();
PORTB = data;
USART_Transmit(data);
}
}
I have commented on Greg's answer, but would like to add one more thing. For this sort of problem the gold standard method of debugging it is to first understand asynchronous serial communications, then to get an oscilloscope and see what's happening on the line. If characters are being exchanged and it's just a baudrate problem this will be particularly helpful as you can calculate the baudrate you are seeing and then adjust the divisor accordingly.
Here is a super quick primer, no doubt you can find something much more comprehensive on Wikipedia or elsewhere.
Let's assume 8 bits, no parity, 1 stop bit (the most common setup). Then if the character being transmitted is say 0x3f (= ascii '?'), then the line looks like this;
...--+ +---+---+---+---+---+---+ +---+--...
| S | 1 1 1 1 1 1 | 0 0 | E
+---+ +---+---+
The high (1) level is +5V at the chip and -12V after conversion to RS232 levels.
The low (0) level is 0V at the chip and +12V after conversion to RS232 levels.
S is the start bit.
Then we have 8 data bits, least significant first, so here 00111111 = 0x3f = '?'.
E is the stop (e for end) bit.
Time is advancing from left to right, just like an oscilloscope display, If the baudrate is 4800, then each bit spans (1/4800) seconds = 0.21 milliseconds (approx).
The receiver works by sampling the line and looking for a falling edge (a quiescent line is simply logical '1' all the time). The receiver knows the baudrate, and the number of start bits (1), so it measures one half bit time from the falling edge to find the middle of the start bit, then samples the line 8 bit times in succession after that to collect the data bits. The receiver then waits one more bit time (until half way through the stop bit) and starts looking for another start bit (i.e. falling edge). Meanwhile the character read is made available to the rest of the system. The transmitter guarantees that the next falling edge won't begin until the stop bit is complete. The transmitter can be programmed to always wait longer (with additional stop bits) but that is a legacy issue, extra stop bits were only required with very slow hardware and/or software setups.
I don't have reference material handy, but the baud rate register UBRR usually contains a divisor value, rather than the desired baud rate itself. A quick google search indicates that the correct divisor value for 4800 baud may be 239. So try:
divisor = 239;
UBRR0H = (unsigned char)(divisor >> 8);
UBRR0L = (unsigned char)divisor;
If this doesn't work, check with the reference docs for your particular chip for the correct divisor calculation formula.
For debugging UART communication, there are two useful things to do:
1) Do a loop-back at the connector and make sure you can read back what you write. If you send a character and get it back exactly, you know that the hardware is wired correctly, and that at least the basic set of UART register configuration is correct.
2) Repeatedly send the character 0x55 ("U") - the binary bit pattern 01010101 will allow you to quickly see the bit width on the oscilloscope, which will let you verify that the speed setting is correct.
After reading the data sheet a little more thoroughly, I was incorrectly setting the baudrate. The ATmega162 data sheet had a chart of clock frequencies plotted against baud rates and the corresponding error.
For a 4800 baud rate and a 1 MHz clock frequency, the error was 0.2%, which was acceptable for me. The trick was passing 12 to the USART_Init() function, instead of 4800.
Hope this helps someone else out!