how to find a default port programmed value in atmega32? - atmega

If the ports of the microcontroller are defined as inputs and the base is not connected to the circuit somewhere
What is the default logical mode of that base (zero or one?) Is it possible to change this state
There is? How can this be done?

My default, ATmega AVR pins are in a state known as high-impedance, which means there is no default voltage. If you do not connect any output to a high-impedance input, we say the pin is floating, and the pin could easily read high or low; you cannot count on it being a particular value.
Every pin has an internal pull-up resistor that you can enable. The pull-up resistor weakly pulls the line up, so that when nothing is driving it, its digital input value will be 1. If you enable the pull-up resistor, the line will no longer be high-impedance or floating.
For example, to set PD2 as an input and enable its pull-up, you can use this C code:
DDRD &= ~(1 << 2);
PORTD |= (1 << 2);

Related

Problems sending SPI Data from STM32 to arduino

I'm trying to learn how to communicate via SPI with STM32 but I've run into some problems.
The first step i took was to implement SPI communications using two arduino unos: the master writes a byte and the slave responds with another byte according to the input (when the master sends anything, triggering the exchange). Everything worked as it should to the best of my knowledge.
The second step is the one I'm stuck at which is to replace the master arduino with a NUCLEO-F767ZI board. I've set up SPI1 using the auto generated code for now, and I've set it up with what I think are the default options. In the main, I send a single byte to the arduino, and this is where the problem starts:
By using the serial port in the arduino I can see that it does receive data, but usually bit shifted. So if I send a 16, i usually get a 32 or other power of two in the arduino (see attached image)
I'm using clock polarity 0 and clock phase 0 on both microcontrollers (so clock idle on low and sampling on the rising edge). Just to be sure I've tried all possibilities but to no avail, it still doesn't work properly, and I don't really know why. Another thing I considered was that perhaps the clock is running too fast (the peripheral clock is set to 16 MHz), but if I change the prescaler to anything other than SPI_BAUDRATEPRESCALER_2, i stop getting any data on the arduino, only 0s, which I find odd, I would expect it to work just the same if only the master controls the clock.
Just for completeness, here are the spi settings I'm using:
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
The arduino slave code (I've removed the reply part for now):
void setup (void)
{
pinMode(MISO, OUTPUT);
Serial.begin(115200);
// turn on SPI in slave mode
SPCR |= _BV(SPE);
// turn on interrupts
SPCR |= _BV(SPIE);
//Check arduino SPI settings, outputs 11000000, so CPHA and CPOL = 0
Serial.println("SPCR");
Serial.println(SPCR,BIN);
} // end of setup
void loop(void){
}
// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;
Serial.println(c);
}
}
STM32 master code (ommiting irrelevant parts):
MX_SPI1_Init();
uint8_t data = 16;
while (1)
{
HAL_SPI_Transmit(&hspi1, &data, 1, 100);
HAL_Delay(500);
}
Does anyone have a clue as to why this could be happening? I've found nothing on the prescaler issues and all bitshifting issue posts say that the problem is with clock phase or polarity discrepancies, which I've verified is not.
Thanks in advance
SPI clock rate input to Atmega328P should be lower than Fosc/4
SPI requires the use of nCS wire. An SPI slave will reset it's logic on deassertion of nCS, but if nCS is always at a low level - any missed clock pulse would propagate to the next transfer, shifting the data.
Stm32F7 has NSSP: NSS pulse management - the option for issuing CLK pulse between data bytes. To deassert nCS pin between larger transfers SPI shoud either be disabled and then reenabled before the next transfer, or nCS management should be implemented in the software. In a later case make sure to deassert nCS only after all CLK pulses are completed.
Arduino UNO have Atmega powered from 5V, Stm32 is powered from 3V (on some boards it's 3.3V). Logic high input minimum for the Atmega328 is 0.6VCC, 5V * 0.6V = 3V, wich is on the edge. See this question
A scope would help a lot to solve such cases.

STM32 Blue pill and Arduino IDE

I want to program Stm32 bluepill with Arduino IDE but when I want to define pins like I write " pinMode(A10, OUTPUT)" it gives error. the error is "'A10' was not declared in this scope"
I want to know how should I declare Pins in Arduino IDE for STM32
Based on the error you're reporting, you're not building your code for the correct board. I suspect you're targeting the ArduinoUNO (default) which does not have an A10.
Also, as hcheung's answer mentions, the name on the blue pill is "PA10".
Follow the instructions here to install the board configuration for the STM "blue pill" then select it and build again.
https://maker.pro/arduino/tutorial/how-to-program-the-stm32-blue-pill-with-arduino-ide
Note, the board selection as of today is now "STM32F1 series" instead of "STM32F103C series" as specified at the link.
One reason could be there is not ADC pin of number 10 for the currently selected board (check the board on tool -> boards), there might be fewer number of ADC pins, e.g. try A0.
Or maybe you have selected wrong board. Bluepill isn't included in the Arduino IDE, by default. So you have to add it to your IDE first.
There is a nice instruction here on how to do this and a sample code.
https://maker.pro/arduino/tutorial/how-to-program-the-stm32-blue-pill-with-arduino-ide
Remember that this newly installed library could have small differences in syntax compared with standard Arduino code, Like this example that is taken from the mentioned site:
void setup() {
// change pin PC13
pinMode(PC13, OUTPUT);
}
//infinite loop
void loop() {
digitalWrite(PC13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(PC13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
As you can see here the pin is selected using "PC13", and not just a number aka "13".
So in this case by installing the library used in the mentioned site you should write PA0 to PA7 for using ADC.
Here is a sample picture displaying the name of the pins and their features:
For STM32 Blue Pill with Arduino Core, digital pins are named based on its port and pin number, such as PB1, PA10.
There is no A10, I assumed that you mean PA10 (which was marked on the Blue Pill PCB as "A10" (for Port A Pin 10) due to limit space on the PCB.
To use it as a digital pin, simply use PA10 to address it, that is:
pinMode(PA10, OUTPUT);
or because PA10 internally happened to be referred as D10, you can also use:
pinMode(10, OUTPUT); //not recommended
For better understanding of all the pin assignments for STM32F103 Blue Pill, please take a look at the source code here and here.

ATTINY 85 SLEEP MODE

I am new to programming microcontrollers and I've just started using Attiny85. I am trying to build a circuit for LED with tactile switch. Every time the tactile switch is pressed it jumps the LED to next state of operation. Since it is battery operated, when the LED is OFF I want the attiny 85 to consume as low current as possible. As of now it is consuming 4mA when the LED is OFF without sleep mode. So I tried the power down mode for Attiny 85 but some how i am stuck in the power down mode
if(count == 8){
analogWrite(0,LOW);
//Serial.println("I am OFF");
//Serial.println(count);
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //Power down everything
sleep_mode();
sleep_disable();
}
It is successfully entering the sleep mode but i am not able to get out of it. Can please someone help. I want the Attiny 85 to get out of the sleep mode when the tactile switch is pressed again. The switch is on pin 7 i.e. PB2 of attiny 85.
Please refer to the datasheet, section 7.1 Sleep Modes at page 34.
In the table you can see, in Power-down mode only 3 sources can wake up the CPU:
INT0, only level interrupt and pin change interrupt
USI module start condition
Watchdog interrupt
That means, if you want the part to wake up when button has been pressed, then best option will be to configure the pin change interrupt.
First you need to configure an interrupt service routine (ISR). The ISR is required just to handle the interrupt event, without it the program will be restarted. Since there is no action required, the ISR can be empty:
#include <avr/interrupt.h>
EMPTY_INTERRUPT(PCINT0_vect);
next you need to configure pin change interrupt (refer to the section 9.2 External Interrupts in the datasheet)
E.g.:
// I don't know which pin do you use for the button
// Let's assue it is PB0 which corresponds to PCINT0
// (see section 1. Pin Configurations)
PCMSK = (1 << PCINT0); // set pin change mask to PCINT0
GIMSK = (1 << PCIE); // enable pin change interrupt
sei(); // enable global interrupts
That's all. After the interrupt is configured, any logical level change at the input will cause the CPU to wake up.

How can I create a serial and read at a certain frequency on a Teensy

I think my question is more of a lack of comprehension, but here is an overview:
I'm trying to discuss with an old Mitsubishi which uses serial communications. The initialization works by toggling the K-Line at 5 bauds (this technique seems to be used elsewhere), then pass the K-Line as INPUT, read some code, and after that you can read and write directly on the K-Line. The details of said protocol (and the fact that we are only using one line) are detailled here.
This messes me up a bit, since I'm used to a TX pin and an RX pin, not having to switch a pin between TX and RX after each read and write, but let's assume this works.
How can I set up a serial communication (specify baudrate and RX/TX pins, which will be the same here) on a Teensy 3.2 ? (classic Arduino C++ stuff)
Or maybe I can have two pins, each connected to the K-Line. This is physically the same but allow me to define it in software as a standard serial.
Here is the written code so far:
void setup() {
// HERE: SETUP SERIAL WITH ONE PIN
// Or do the two-pins-on-same-wire-thing with HWSerial.begin(15625, SERIAL_8N1);
pinMode(DATA_PIN, OUTPUT);
// MUT Init
int init = MUT_INIT_CODE;
for (int i= 0; i < 9; i++){
if (init & 1){
digitalWrite(DATA_PIN, HIGH);
digitalWrite(LED_PIN, HIGH);
} else {
digitalWrite(DATA_PIN, LOW);
digitalWrite(LED_PIN, LOW);
}
init >>= 1;
delay(MUT_INIT_DELAY);
}
byte answer[3];
pinMode(DATA_PIN, INPUT);
HWSerial.readBytes(answer, 3);
}
Thanks in advance!
Technically you can not tie RX and TX together, because a hardware serial module (like the one inside the Teensy) will drive TX high by default, so RX would be always high as well. You need to configure your pin sometimes as an input, sometimes as an output.
You can not use a hardware serial module because the TX and RX pins are predefined and separate, and you should try using a software serial emulation library like https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
Try changing the code to add a function to reconfigure your unique pin as an input or output, as needed, and declare the same pin for TX and RX.
edit: a hardware approach would be to use an analog multiplexer like the MAX4619. This way you can use a hardware serial module on the Teensy, connect TX and RX to the multiplexer's X0/X1 pins, and the K-line on the X pin. You can toggle the multiplexer's A command pin with a Teensy GPIO.
I didn't test this approach because I don't have this kind of car, but it might be worth giving it a try.
edit2: to answer more specifically the op's question, the pins of the serial modules of the teensy are hardwired. On a Teensy 3.2, Serial1 is connected to pins 0/1 or 5/21, Serial2 to pins 9/10 or 26/31, etc. The list is available here: https://www.pjrc.com/teensy/td_uart.html
The baud rate is configured by calling Serial1.begin(YOUR_BAUD_RATE);

STM32 communication with A4899 stepper motor driver

I want to write a stepper motor driver with a STM32L152RE.
I would like to control the position of the stepper motor with a potentiometer.
As I am new, I do not know how to communicate with (DIR, STEP).
Can someone give me a light or show me a way?
I'm using an A4988 - DMOS Microstepping Driver with Translator And Overcurrent Protection
I tried to use STM32 tim, but I could not.
Actually I have wrote whole driver for a4988, it is irq based. But I can't uncover it.
I can describe a path how to start. Anyway you should have some kind of hardware, because A4988 needs extra components for current control (resistors), and some capacitors..
You could try POLOLU HW.
If you have some kind of custom board, there may be some flaws.. So recheck pins.
Especially ROSC pin, SENSE1, SENSE2 pins as those may cause that motor wont work even if other pins are ok.
ROSC pin is for low power mode, so here you should calculate, if you just ignore it, be sure to connect at least to 10k resistor. Don't let it float. SENSE1, SENSE2 pins can be connected to 0.25omh resistors. You should check it.
Also from power pins very decisive VREG pin. It should get from 0 to 2000mV if I remember. Actually it controls current for your motor. So it depends on your stepper motor. Here also may appear nasty flaws. For example you have small stepper motor, and setting too high VREG value, than A4988 will sink too much current and your motor will glitch. Anyway you should read A4988 data sheet very accurately.
DIR PIN is simply for direction, push-pull pin configuration and HIGH/LOW values controls direction, clock wise, anti clock wise.
RESET INPUT PIN A4988 must get HIGH from your MCU.
ENABLE INPUT PIN A4988 must get LOW from your MCU.
SLEEP INPUT PIN A4988 must get HIGH from your MCU, also it is very useful to control it when your stepper job done, else if you leave it always HIGH, stepper motor will eat current and will heat up at idle state.
Also there are 3 MICROSTEPPING PINS, those are for controlling stepping.
As you just starting to play, it will be enough connect those pins to GND, you'll get full stepping regime.If you'll control those pins you can get other regimes like 1/2 stepping, 1/4,1/8,1/16...
And general pin is STEP pin, it should be driven with TIMER as PWM output with constant pulse width and alternating period.
Here is an example of STEP PIN control:
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
GPIO_InitTypeDef init;
init.GPIO_Mode = GPIO_Mode_AF;
init.GPIO_OType = GPIO_OType_PP;
init.GPIO_Pin = GPIO_Pin_9;
init.GPIO_PuPd = GPIO_PuPd_UP;
init.GPIO_Speed = GPIO_Speed_Level_2;
GPIO_Init(GPIOA,&init);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_2);
for example I connect STEP output from MCU PA9 to A4988 STEP input. Which can be driven from timer as PWM. Check your concrete MCU datasheet.
Firstly output pin should be configured as AF, with push-pull and resistor is UP.
Also setup line for alternating pin.
Now configuring timer:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 48;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = 0;
timerInitStructure.TIM_ClockDivision = 0;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &timerInitStructure);
TIM_OCInitTypeDef osc;
osc.TIM_OCMode = TIM_OCMode_PWM1;
osc.TIM_OutputState = TIM_OutputState_Enable;
osc.TIM_OutputNState = TIM_OutputNState_Disable;
osc.TIM_Pulse = 1000;
osc.TIM_OCPolarity = TIM_OCNPolarity_High;
osc.TIM_OCNPolarity = TIM_OCNPolarity_Low;
osc.TIM_OCIdleState =TIM_OCIdleState_Reset;
osc.TIM_OCNIdleState =TIM_OCNIdleState_Set;
TIM_OC2Init(TIM1, &osc);
TIM_Cmd(TIM1, ENABLE);
Here I configure 1us timer, as my MCU frequency is 48MHz.
Also you have configure that timer would drive PWM output.
TIM1->CCR = 10; with this register I can control pulse width, in this example it is 10us.
TIM1->ARR = 30; with ARR register I can control period, so it means STEP pulse frequency which is equal to stepper motor speed. In this case 30us.
If you are using HAL and CUBEMX you can get those configurations pretty fast.

Resources