Unable to read certain inputs of STM32F446RE microcontroller - c

Everyone, I wanted to take 8 inputs from the STM32F446RE Microcontroller. But I am getting right inputs (1 when not in GND and 0 when in GND) from only 3 pins (PC0, PA0 and PB0) in my Microcontroller. I am getting always 0 for other pins (even it is not in ground). Used the debugging mode too to debug this for 1 week. But I am not getting the right input values. Am I doing something wrong? Am I missing something in my code? I am attaching my whole code here. The purpose of this code is to take two 4 group of bits as input and sum the bits and output the summation of bits. (Bit wise summation). Please help me out here. I am starting to think the Microcontroller I got is broken. But I also used 2 microcontrollers to check the error. Same thing happens to both of the microcontrollers.
#include<stm32f446xx.h>
#include<math.h>
#define INPUTA0 (GPIOC->IDR & (1 << 0)) //PC0 Input
#define INPUTA1 (GPIOA->IDR & (1 << 0)) //PA0 Input
#define INPUTA2 (GPIOB->IDR & (1 << 0)) //PB0 Input
#define INPUTA3 (GPIOC->IDR & (1 << 1)) //PC1 Input
#define INPUTB0 (GPIOA->IDR & (1 << 13)) //PA13 Input
#define INPUTB1 (GPIOA->IDR & (1 << 14)) //PA14 Input
#define INPUTB2 (GPIOA->IDR & (1 << 15)) //PA15 Input
#define INPUTB3 (GPIOB->IDR & (1 << 7)) //PB7 Input
void outputCheck(int binarySum[]){
if(binarySum[0] == 0){
GPIOB->BSRR |= 0x1000000; //PB8 off
}
if(binarySum[1] == 0){
GPIOB->BSRR |= 0x2000000; //PB9 off
}
if(binarySum[2] == 0){
GPIOA->BSRR |= 0x200000; //PA5 off
}
if(binarySum[3] == 0){
GPIOA->BSRR |= 0x400000; //PA6 off
}
if(binarySum[4] == 0){
GPIOA->BSRR |= 0x800000; //PA7 off
}
if(binarySum[5] == 0){
GPIOB->BSRR |= 0x400000; //PB6 off
}
if(binarySum[6] == 0){
GPIOC->BSRR |= 0x800000; //PC7 off
}
if(binarySum[7] == 0){
GPIOA->BSRR |= 0x2000000; //PA9 off
}
if(binarySum[0] == 1){
GPIOB->BSRR |= 0x100; //PB8 on
}
if(binarySum[1] == 1){
GPIOB->BSRR |= 0x200; //PB9 on
}
if(binarySum[2] == 1){
GPIOA->BSRR |= 0x20; //PA5 on
}
if(binarySum[3] == 1){
GPIOA->BSRR |= 0x40; //PA6 on
}
if(binarySum[4] == 1){
GPIOA->BSRR |= 0x80; //PA7 on
}
if(binarySum[5] == 1){
GPIOB->BSRR |= 0x40; //PB6 on
}
if(binarySum[6] == 1){
GPIOC->BSRR |= 0x80; //PC7 on
}
if(binarySum[7] == 1){
GPIOA->BSRR |= 0x200; //PA9 on
}
}
double binaryToDecimal(int inputVal[]){
double ans = 0;
int powerVal = 3;
for(int i=0;i<4;i++){
if(inputVal[i] == 1){
ans = ans + pow(2, powerVal);
}
powerVal--;
}
return ans;
}
int main(){
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN;
GPIOB->MODER |= 0x10000; //PB8 OUTPUT
GPIOB->MODER |= 0x40000; //PB9 OUTPUT
GPIOA->MODER |= 0x400; //PA5 OUTPUT
GPIOA->MODER |= 0x1000; //PA6 OUTPUT
GPIOA->MODER |= 0x4000; //PA7 OUTPUT
GPIOB->MODER |= 0x1000; //PB6 OUTPUT
GPIOC->MODER |= 0x4000; //PC7 OUTPUT
GPIOA->MODER |= 0x40000; //PA9 OUTPUT
while(1){
int input1Array[4] = {INPUTA0,INPUTA1,INPUTA2,INPUTA3}; // input1
int input2Array[4] = {INPUTB0, INPUTB1, INPUTB2, INPUTB3}; // input2
// input binary to decimal value
double input1ToDecimal = binaryToDecimal(input1Array);
double input2ToDecimal = binaryToDecimal(input2Array);
// total sum of the input1 and input2
int ans = (int) input1ToDecimal + (int) input2ToDecimal;
int binarySum[8];
// turning total sum to binary number finally
for(int i = 0; ans > 0; i++){
binarySum[i] = ans % 2;
ans = ans / 2;
}
//answer
outputCheck(binarySum);
}
}

If someone is in my situation then use GPIOx_PUPDR and set it to pull up (01). Then take the input value as uint32_t variable.

Related

How can i use IDR

I am trying to make an state machine with button. When i press the button, state will change. But I can not read the button from IDR. How can i read the button press with IDR ? if( GPIOA->IDR |= (1U << 1) ) this part has a problem i think or should i enable some registers or clocks ?
`
int main(void) {
uint32_t ButtonPress = 0;
/* Enable GPIOA clock */
RCC->IOPENR |= (1U << 0);
/* Setup PA0 as output */
GPIOA->MODER &= ~(3U << 2*0);
GPIOA->MODER |= (1U << 2*0);
/* Setup PA1 as input */
GPIOA->MODER &= ~(3U << 2*1);
GPIOA->MODER |= (0U << 2*1);
/* Setup PA1 as Button1 */
// GPIOA->IDR |= (1U << 1);
while(1) {
if( GPIOA->IDR |= (1U << 1) )
ButtonPress++;
if(ButtonPress == 0)
/* Turn off LED */
GPIOA->ODR ^= (1U << 0);
else if(ButtonPress == 1){
/* Turn on LED 2sec interval */
GPIOA->ODR |= (1U << 0);
delay(LEDDELAY);
delay(LEDDELAY);
GPIOA->ODR ^= (1U << 0);
delay(LEDDELAY);
delay(LEDDELAY);
}
else if(ButtonPress == 2){
/* Turn on LED 1sec interval */
GPIOA->ODR |= (1U << 0);
delay(LEDDELAY);
GPIOA->ODR ^= (1U << 0);
delay(LEDDELAY);
}
else if(ButtonPress == 3){
/* Turn on LED 0.5sec interval */
GPIOA->ODR |= (1U << 0);
delay(LEDDELAY/2);
GPIOA->ODR ^= (1U << 0);
delay(LEDDELAY/2);
}
else if(ButtonPress == 4){
/* Turn on LED 0.1sec interval */
GPIOA->ODR |= (1U << 0);
delay(LEDDELAY/10);
GPIOA->ODR ^= (1U << 0);
delay(LEDDELAY/10);
}
else if(ButtonPress == 5){
/* Turn on LED */
GPIOA->ODR |= (1U << 0);
}
else
/* Button Reset */
ButtonPress = 0;
}
return 0;
}
`
I am trying to make an state machine with button. When i press the button, state will change. But I can not read the button from IDR.
You are attempting to write to the IDR with this line
if( GPIOA->IDR |= (1U << 1) )
Since the IDR is read-only, the statement always evaluates to false.
Instead, you should use:
if (GPIOA->IDR & GPIO_PIN_1) { // GPIO_PIN_1 is a macro for (1U << 1)
ButtonPress++;
}
to evaluate the value of GPIOA pin 1.

How can i set encoder mode at stm32 h7?

I'm trying to get encoder data to my stm32 h7 and display counter value through uart.
I can see counter value 0 through my uart terminal but counter value never goes up...
I'm using encoder mode.
Please, help me to do this
static void Encoder_init(void)
{
RCC->APB2RSTR &= ~(1 << 1);
RCC->APB2ENR |= (1 << 1); //TIM8 clk enable
TIM8->CR1 &= ~(1 << 0); //tim8 disable
TIM8->SMCR |= (0x03 << 0); //SMS set
TIM8->CCER &= ~(1 << 1); //CC1P
TIM8->CCER &= ~(1 << 5); //CC2P
TIM8->CCER &= ~(1<<3); //CC1NP LOW
TIM8->CCER &= ~(1<<7); //CC2NP LOW
TIM8->CCMR1 |= (1<<0); //CC1S
TIM8->CCMR1 |= (1<<8); //CC2S
TIM8->PSC = 0; //prescaler zero
TIM8->ARR = 0xFFFF;
TIM8->CR1 |= (1 << 0); //tim8 enable}
}
void tEncoder(void *pvParameters)
{
uint8_t encoder_data;
char buf[4];
char val;
RCC->AHB4RSTR &= ~(1 << 2);
RCC->AHB4ENR |= (1 << 2);
GPIOC->MODER &= ~(0x03 << 12);
GPIOC->MODER &= ~(0x03 << 14);
GPIOC->PUPDR |= (1<<6) | (1<<7);
Encoder_init();
while(1) {
vTaskDelay(1000);
if(encoder_data!=TIM8->CNT) {
encoder_data = TIM8->CNT;
int2str(buf, encoder_data);
uart7_buffer_putstr(buf);
SystemPrint("tEncoder counting\n\r");
}
}
}

C - atmega328p - I don't understand what is wrong

i do not unterstand why my code isnt working(doISR). What its supposed to do:
-there is a running light(6 LEDs) and 3 Buttons. I need to press the button at the right time(Button 1, if LED 1 or 2 is on....etc). if its correct: increase the speed, if not: reset.
i bet its a blunder, but i dont get it :)
void wait(void) {
while (!(TIFR1 & (1 << OCF1A))) // wait
;
TIFR1 |= (1 << OCF1A); // delete Interrupt flag
}
volatile bool ISRhasHappend = false;
ISR(PCINT0_vect) {
ISRhasHappend = true;
}
int main(void) {
OCR1A = 3125 - 1; //2 seconds
TCCR1B |= (1 << WGM12); //turn on CTC mode
TCCR1B |= (1 << CS12) | (1 << CS10); //Prescalemode 101 -> 1024 Takt
DDRB = (1 << PCINT5);
DDRC = 0x3f;
PCICR = 0x3f; //Pin Change Interrupt Control Register
PCMSK0 = (1 << PCINT0) | (1 << PCINT2) | (1 << PCINT4);
sei();
doRunningLight();
if (ISRhasHappend == true) {
doISR();
}
}
void doISR() {
//while timee >0
for(int x=3125;x>0;x=x-250){
//if LEDs 0+1 on, and button0 pressed ...etc
if ((PORTC & (0b00000011)) && (PINB & (1 << PINB0)) || (PORTC &
(0b00001100)) && (PINB & (1 << PINB2)) || (PORTC & (0b00110000)) &&
(PINB & (1 << PINB4))) {
//All led lights up
PORTC |= 0x3f;
wait();
//reduce timer if catched the light
OCR1A = x;
}
else {
//turn signal
for (int y = 1; y < 5; y++) {
PORTB ^= (1 << PCINT5);
wait();
}
//back to 3124 if failed
OCR1A = 3125 - 1;
}
}
ISRhasHappend = false;
}
void doRunningLight(){
while(1) {
for (int i = 0; i<6; i++){
PORTC |= (1<<i);
wait();
PORTC &= ~(1<<i);
}
}
}
The function doRunningLight() never returns, so the code that you wrote after it to check ISRhasHappend and call doIsr will never run. You will need to think of a different way to handle your events, probably without using blocking delay loops.
I would also question whether you actually need a pin-change interrupt. Button presses are slow enough that your microcontroller should be able to detect them by reading the pin in the main loop.

Set OCR register in interrupt?

On ATmega 32u4 I've got two timers. One is for measuring ticks between interrupts and second which counts 1/60 of number of ticks. I'm not sure I'm allowed what I'm doing and if that is correct. If you could tell me what is wrong I would greatfull.
void setup(){
EIMSK |= (1 << INT2); //INT2 enable
EICRA |= (1 << ISC21) | (1 << ISC20); //INT2 RISING EDGE
DDRD &= ~(1 << PD2); //PD0 (INT0)(3) as input
PORTD &= ~(1 << PD2); //PD0 pulldown
TCCR1B |= (1 << CS11); //prescaler 8
//TIMER3 - 1/60
TCCR3A |= (1 << WGM32); //CTC Mode
TCCR3B |= (1 << CS31); //prescaler 8
TIMSK3 |= (1 << OCIE3A); //compate interrupt enable
sei();
}
ISR(INT2_vect) {
TCNT3 = 0;
OCR3A = TCNT1 / 60;
TCNT1 = 0;
degree = 30;
}
ISR(TIMER3_COMPA_vect) {
Color * currentColor = &bColor;
if (degree == 0)
degree = 59;
else degree--;
if (degree == time.second)
currentColor = &sColor;
else if (degree == time.minute)
currentColor = &mColor;
else if (degree % 5 == 0 && degree / 5 == time.hour)
currentColor = &hColor;
//set pwm
RedReg = currentColor->Red;
GreenReg = currentColor->Green;
BlueReg = currentColor->Blue;
}

STM32F207 I2C test failing

I am learning embedded development on the STM3220G-EVAL board with the STM32F207 microcontroller. I have tried to test the I2C interface by interfacing the two I2C2 and I2C3 modules on the same chip and sending/receiving a character. Here is the code I have currently written (using mdk-arm 5):
#include <stm32f2xx.h>
volatile uint8_t data = 'a', recv = 'x';
void i2c_init(void);
void I2C2_EV_IRQHandler(void)
{
volatile uint16_t stat, dummy;
stat = I2C2->SR1;
switch(stat)
{
// SB set; read SR1 and write slave address in DR to clear
case 0x01:
dummy = I2C2->SR1;
// Send address of slave
I2C2->DR = (0x08 << 1);
break;
// ADDR set; read SR1 and SR2 to clear
case 0x02:
dummy = I2C2->SR1;
dummy = I2C2->SR2;
break;
// TxE set; write to DR to clear
case 0x80:
I2C2->DR = data;
break;
// TxE and BTF set; generate stop condition to clear
case 0x84:
// Generate stop
I2C2->CR1 |= (1 << 9);
break;
}
}
void I2C3_EV_IRQHandler(void)
{
volatile uint16_t stat, dummy;
stat = I2C3->SR1;
switch(stat)
{
// ADDR set; read SR1 and SR2 to clear
case 0x02:
dummy = I2C3->SR1;
dummy = I2C3->SR2;
break;
// STOPF set; read SR1 and write CR1 to clear
case 0x10:
dummy = I2C3->SR1;
I2C3->CR1 &= ~(1 << 0);
break;
// RxNE set; read DR to clear
case 0x40:
recv = I2C3->DR;
break;
}
}
int main()
{
i2c_init();
// Generate START condition
I2C2->CR1 |= (1 << 8);
while(1)
{
if(!(I2C2->OAR1 & (1 << 14)))
I2C2->OAR1 |= (1 << 14);
if(!(I2C3->OAR1 & (1 << 14)))
I2C3->OAR1 |= (1 << 14);
if(recv != 'x')
break;
}
return 0;
}
void i2c_init(void)
{
// Enable GPIOA, GPIOC, GPIOF, I2C2 and I2C3 peripherals
RCC->AHB1ENR |= (1 << 0);
RCC->AHB1ENR |= (1 << 2);
RCC->AHB1ENR |= (1 << 5);
RCC->APB1ENR |= (1 << 22);
RCC->APB1ENR |= (1 << 23);
// Set GPIO mode to AF
GPIOA->MODER |= (1 << 17);
GPIOC->MODER |= (1 << 19);
GPIOF->MODER |= (1 << 1);
GPIOF->MODER |= (1 << 3);
// Set GPIO type to OD
GPIOA->OTYPER |= (1 << 8);
GPIOC->OTYPER |= (1 << 9);
GPIOF->OTYPER |= (1 << 0);
GPIOF->OTYPER |= (1 << 1);
// Set GPIO speed to 50MHz
GPIOA->OSPEEDR |= (1 << 17);
GPIOC->OSPEEDR |= (1 << 19);
GPIOF->OSPEEDR |= (1 << 1);
GPIOF->OSPEEDR |= (1 << 3);
// Link to AFs
GPIOA->AFR[1] |= (1 << 2);
GPIOC->AFR[1] |= (1 << 6);
GPIOF->AFR[0] |= (1 << 2);
GPIOF->AFR[0] |= (1 << 6);
// Reset clocks
I2C2->CR2 = 0x00;
I2C3->CR2 = 0x00;
I2C2->CCR = 0x00;
I2C3->CCR = 0x00;
// Enable interrupts
I2C2->CR2 |= (1 << 9);
I2C2->CR2 |= (1 << 10);
I2C3->CR2 |= (1 << 9);
I2C3->CR2 |= (1 << 10);
NVIC_EnableIRQ(I2C2_EV_IRQn);
NVIC_EnableIRQ(I2C3_EV_IRQn);
// Must set bit 14 in OAR1 to 1
I2C2->OAR1 |= (1 << 14);
I2C3->OAR1 |= (1 << 14);
// Set addresses
I2C2->OAR1 = (0x04 << 1);
I2C3->OAR1 = (0x08 << 1);
// Set peripheral clock frequency
I2C2->CR2 |= 0x08;
I2C3->CR2 |= 0x08;
I2C2->CCR |= 0x28;
I2C3->CCR |= 0x28;
I2C2->TRISE = 0x09;
I2C3->TRISE = 0x09;
// Enable ACK
I2C2->CR1 |= (1 << 10);
I2C3->CR1 |= (1 << 10);
// Enable I2C peripherals
I2C2->CR1 |= (1 << 0);
I2C3->CR1 |= (1 << 0);
}
The problems I am facing are:
The execution never goes into the interrupt handlers (verified by
breakpoints)
The SB bit in SR1 of the master (I2C2) is never set even though i have set the START bit in CR1
The SDA line is HIGH but the SCL line is pulled LOW
I am using a pullup of 13K on SDA and 10K on SCL. Pin numbers used are PF0, PF1 (I2C2 SDA, SCL) and PA8, PC9 (I2C3 SCL, SDA). Using the internal or external pullups causes the SR2 register to display that the bus is busy.
Also I have not enabled I2C2 and I2C3 in RTE_Device.h. It just seems to provide convenience typedefs. (EDIT : Tried to enable these, it does not help)
Could anyone help me in solving this problem? I seem to have hit a dead end.
(EDIT : After setting up a few jumpers on the board, the master event handler is successfully being called. But still some problems persist. Now the acknowledge failure bit is being set, and the slave handler is not called. Bus lines have been verified to be HIGH when idle.)
Sorry for the delay in mentioning this, but I have successfully solved this problem by using the STM32 CPAL library available from ST. I have tested this library with the onboard accelerometer by reading the 'WHO_AM_I' register in the accelerometer. The code for this is:
#include "cpal_i2c.h"
int main()
{
// Configuration
CPAL_TransferTypeDef RxStruct;
uint8_t RxBuf;
RxStruct.pbBuffer = &RxBuf;
RxStruct.wAddr1 = 0x39;
// Initialization
CPAL_I2C_StructInit(&I2C1_DevStructure);
I2C1_DevStructure.CPAL_Mode = CPAL_MODE_MASTER;
I2C1_DevStructure.CPAL_ProgModel = CPAL_PROGMODEL_DMA;
I2C1_DevStructure.pCPAL_I2C_Struct->I2C_ClockSpeed = 100000;
I2C1_DevStructure.pCPAL_TransferRx = &RxStruct;
I2C1_DevStructure.pCPAL_TransferTx = pNULL;
CPAL_I2C_Init(&I2C1_DevStructure);
// Communication
RxStruct.wNumData = 1;
RxStruct.wAddr2 = 0x0F;
if(CPAL_I2C_Read(&I2C1_DevStructure) != CPAL_PASS)
{
// Error
}
while(I2C1_DevStructure.CPAL_State != CPAL_STATE_READY);
while(1);
return 0;
}

Resources