I'm trying to stop the user from pressing the button for 1 second if it has already been pressed. Can this be done without using the superloop in main.c?
My EXTI0 is in stm32f4xx_it.
void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
if (HAL_GPIO_ReadPin (GPIOA,GPIO_PIN_0))
{
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
TIM1_TRG_COM_TIM11_IRQHandler();
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin (GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
}
/* USER CODE END EXTI0_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
/* USER CODE BEGIN EXTI0_IRQn 1 */
/* USER CODE END EXTI0_IRQn 1 */
}
If the user press a button you can get the syste time and save it inside a variable. if the user press again, you can check, if enough time has passed. The example is just for show the mechanism and is just one possibility to solve your problem.
int nLastPress = 0;
void EXTI0_IRQHandler(void)
{
if(nLastPress + 1 < SYSTEM_TIME_IN_SECONDS)
{
// do your stuff
nLastPress = SYSTEM_TIME_IN_SECONDS;
}
else
{
// don't handle user input
}
}
Related
I have a small program running on stm32wb55. It tests the TIM2 timer with a delay function called wait_us(). The program runs correctly when I compile it with Keil uVision 5, but when I compile it with STM32CubeIDE it gets stuck in the function get_us(). Is there a bug in STM32CubeIDE?
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void PeriphCommonClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
extern void initialize_tim2(void);
extern void wait_us(volatile uint32_t us);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
initialize_tim2();
TIM2->CR1 |= 0x0001;
wait_us(10);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_GPIO_TogglePin(GPIOB, LD1_Pin);
HAL_Delay(500);
}
/* USER CODE END 3 */
}
#include "stm32wbxx.h"
volatile uint32_t tim2_counter;
void initialize_tim2(void)
{
RCC->APB1ENR1 |= 0x00000001;
TIM2->CR1 = 0x0004;
TIM2->CR2 = 0x0000;
TIM2->PSC = 0;
TIM2->ARR = 32;
TIM2->DIER = 0x0001;
TIM2->CNT = 0;
NVIC_SetPriority(TIM2_IRQn, 0);
tim2_counter = 0;
}
void TIM2_IRQHandler(void)
{
TIM2->SR &= (~0x001F);
++tim2_counter;
}
uint32_t get_us(void)
{
return tim2_counter;
}
void wait_us(volatile uint32_t us)
{
volatile uint32_t tickstart, now, IRQ_status;
// Get current interrupt status of TIM2 and enable it.
// Needs to be done with all interrupts disabled to prevent race condition?
__disable_irq();
IRQ_status = NVIC_GetEnableIRQ(TIM2_IRQn);
NVIC_EnableIRQ(TIM2_IRQn);
__enable_irq();
tickstart = get_us();
now = tickstart; //<-processing never reaches here under STM32CubeIDE.
while((now - tickstart) < us)
{
now = get_us();
}
// Return to previous interrupt status of TIM2.
// Needs to be done with all interrupts disabled to prevent race condition?
__disable_irq();
if(0 == IRQ_status)
{
NVIC_DisableIRQ(TIM2_IRQn);
}
else
{
NVIC_EnableIRQ(TIM2_IRQn);
}
__enable_irq();
}
I have a push button PC13 and my LED PA5. I want to push my button so that the current state (on, off and toggle) switches to the next one. So for example: The LED is currently on, I push a button, LED switches off, I push the button again and it toggles, I push the button again and it stays on, and so on. When I debug this the counter variable switches to the desired number I am currently at and while I debug this it works perfectly fine. However, as soon as I upload it to the board it doesn't work like in debug state. It is on and then toggles and every additional button push doesn't change.
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
int counter = 0;
while (1)
{
int stateOfPushButton = 0;
if (!HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 1){ //Check if button pressed
HAL_Delay(5); //check for bounce
if (!HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 1){
stateOfPushButton = 1;
}
}
counter = (counter + stateOfPushButton)%3;
if(counter == 0){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5,GPIO_PIN_SET); //Led Switch On
}
else if(counter == 1){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5,GPIO_PIN_RESET); //Led Switch Off
}
else{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Led toggled
HAL_Delay(1000);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
EDIT:
I added a delay function to check for bounces in the button, proposed by #Jose and the problem persists.
EDIT 2:
It works better, although not ideal, when decreasing the delay function. I guess, my interrupt gets into conflict with the delay function.
The problem was as I suspected in the second EDIT that my interrupt gets into conflict with the delay function in toggle mode. This is due to the circumstance that the while loop continues to loop over and always gets caught in the second delay function. This makes interrupting very hard, since you need to time the interrupt always when in toggle mode it is not caught in the delay function.
To avoid this, simply increase the first delay function, which is responsible to avoid signal bounces, so that it gets longer than the second delay function in toggle mode.
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
int counter = 0;
while (1)
{
int stateOfPushButton = 0;
if (!HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 1){ //Check if button pressed
HAL_Delay(1000); //check for bounce
if (!HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == 1){
stateOfPushButton = 1;
}
}
counter = (counter + stateOfPushButton)%3;
if(counter == 0){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5,GPIO_PIN_RESET); //Led Switch Off
}
else if(counter == 1){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5,GPIO_PIN_SET); //Led Switch On
}
else{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Led toggled
HAL_Delay(20);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
The Code is generated by CubeIde(Mx).
So on the second run of the main loop the ADC Error register reads 4 and stops working (Status register reads 320).
The ADC is configured to read 2 Channels (1.5 cycles) (scan forward) and the ADC clock is the main clock divided by 4 (48/4=12MHz).
The DMA is configured as half word and circular.
The timers are configured to 40kHz.
I have checked that the used array are correct size. The optimization does not seam to change the behavior.
HAL_ADCEx_Calibration_Start(&hadc); //ADC SETUP
HAL_ADC_Stop(&hadc);
HAL_TIM_Base_Start(&htim1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
cc = 0;
flag = 1; //Start
HAL_TIM_Base_Start_IT(&htim3);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
while (flag != 0) { // Measurement on going
//HAL_Delay(1);
if (flag == 0) {
HAL_ADC_Stop_DMA(&hadc);
}
}
HAL_ADC_Stop_DMA(&hadc);
for (uint16_t i = 0; i < 800; ++i) {
sprintf(asic_buffer, "%d", guffer[i]);
asic_buffer[4] = 0;
HAL_UART_Transmit(&huart1, asic_buffer, 5, 20);
HAL_UART_Transmit(&huart1, new_line, 2, 8);
}
HAL_Delay(1);
}
the fist interrupt
void TIM3_IRQHandler(void) {
/* USER CODE BEGIN TIM3_IRQn 0 */
if (flag == 1) {
flag_c++;
if (flag_c >= pulse) {
flag = 2; //Listening
flag_c = 0;
HAL_TIM_Base_Stop_IT(&htim3);
HAL_TIM_Base_Stop(&htim1);
HAL_ADC_Start_DMA(&hadc, (uint32_t*) buffera, 8); //ADC Start
//pos = 0;
//datacounter = 0;
}
}
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */
/* USER CODE END TIM3_IRQn 1 */
}
the second interrupt
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
if (cc * 4 >= 800) {
flag = 0;
}
++cc;
}
Thank you for reading :)
The error lies with in the HAL_ADC_Stop_DMA(&hadc) witch should be HAL_ADC_Stop(&hadc).
i don't know why but it solves the Error.
I have a PIC12F1822 of which there is an LED and relay as an output and a trigger as an input.
When the trigger is equal to one, I would like the to have the LED and relay stay turned on for 90 minutes.
The problem is that I cannot use a delay since __delayms has a limit.
How can this be done?
#include <xc.h>
#define _XTAL_FREQ 4000000
#define LED PORTAbits.RA5
#define RELAY PORTAbits.RA4
#define TRIGGER PORTAbits.RA2
int main()
{
// OSCCON = 0b01101000 ;
OSCCONbits.IRCF = 0b1101 ;
TRISAbits.TRISA5 = 0; //LED Output PIN
TRISAbits.TRISA4 = 0; //Output for Relay
TRISAbits.TRISA2 = 1; //INPUT trigger from comparator
while(1)
{
if (TRIGGER == 1)
{
LED = 1; // LED ON
__delay_ms(1000); // 1 Second Delay
LED = 0; // LED OFF
__delay_ms(1000); // 1 Second Delay
}
else
{
LED = 0; // LED OFF
}
}
return 0;
}
why not wrap the 1s delay in a function providing a delay_s(uint32_t seconds) and in a function providing a delay_m(uint32_t minutes)
void delay_s(uint32_t seconds)
{
while(seconds){
__delay_ms(1000);
seconds--;
}
}
void delay_m(uint32_t minutes)
{
while(minutes){
delay_s(60);
minutes--;
}
}
But:
You should be aware that this totally blocks your µC's program.
It will not react on any key press. This may be ok but may be you want the delay to be reset to 90min if the key is pressed during the delay.
I would suggest to implement the whole thing with interrupts and timers.
Set up a timer that triggers once every second and countdown a global variable (volatile!) within the isr that was set by your main loop. If the counter reaches 0 your isr may disable your output.
This way your µC can process other things in the mainloop and is not blocked by a __delay-function.
Simple. State machines and timer interrupts and a minute countdown. Something like this:
Disclaimer - coded blindly
#define MINUTES_90 5400UL /* 90 seconds */
typedef enum
{
/** Code operational */
p_state_idle,
/** Code waiting for 90 minutes */
p_state_waiting
}p_state_t;
static unsigned long gSecondsRemaining = MINUTES_90;
int main()
{
p_state_t gState = p_state_running;
OPTION_REGbits.PSA = 0; /* Prescaler assigned */
OPTION_REGbits.PS = 0b111; /* 256 prescaler */
OPTION_REGbits.TMR0CS = 0; /* Fosc / 4 */
INTCONbits.TMR0IE = 1; /* Timer 0 interrupt enabled */
INTCONbits.PEIE = 1; /* Peripheral interrupts enabled */
INTCONbits.GIE = 1; /* Global interrupts enabled */
/** Default LED off */
LED = 0;
while (1)
{
switch (gState)
{
case p_state_idle:
if (TRIGGER == 1)
{
LED = 1; // LED ON
gSecondsRemaining = MINUTES_90; /* Reset timer countdown */
gState = p_state_waiting;
}
break;
case p_state_waiting:
/** can sleep here */
if (gSecondsRemaining == 0)
{
gState = p_state_idle;
LED = 0;
}
break;
}
}
}
void interrupt ISR()
{
static unsigned char gSecond = 15;
/** approx 15 Hz ? */
if (INTCONbits.TMR0IF)
{
INTCONbits.TMR0IF = 0;
if (gSecond > 0)
gSecond--;
if (gSecond == 0)
{
if (gSecondsRemaining > 0)
gSecondsRemaining--;
gSecond = 15;
}
}
}
You could solve this with an inline assembly function with some loops. Have a look here: example: 30 min delay
I'm beginer in STM32, i have a project and need to receive data from another device like arduino, and now I try transmit data from UART 3 and I receive data with UART 1. but I can't get any data. I connect TX uart 3 to RX uart 1 and TX uart 1 to RX uart 3.
/* USER CODE BEGIN PV */
int i = 0;
char bufferReceive[6], bufferTransmit[10];
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Receive_IT(&huart1, (uint8_t*)bufferReceive, 1); //activate UART receive interrupt every time
}
}
/* USER CODE END 0 */
int main(void)
{
HAL_UART_Receive_IT(&huart1, (uint8_t*)bufferReceive, 1);
while (1)
{
/* USER CODE END WHILE */`enter code here`
sprintf(bufferTransmit,"%d\n",i);
HAL_UART_Transmit(&huart3, (uint8_t*)bufferTransmit, sizeof(bufferTransmit), 1000);
HAL_Delay(500);
i++;
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
First thing your code is messy and hard to read.
Second, you are missing your entire initialization region before while(1) so your system shouldn't be doing anything.
/* USER CODE BEGIN PV */
int i = 0;
char bufferReceive[6], bufferTransmit[10];
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
HAL_UART_Receive_IT(&huart1, (uint8_t*)bufferReceive, 1);
}
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t*)bufferReceive, 1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
sprintf(bufferTransmit,"%d\n",i);
HAL_UART_Transmit(&huart3, (uint8_t*)bufferTransmit, sizeof(bufferTransmit), 1000);
HAL_Delay(500);
i++;
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
You are receiving one byte at HAL_UART_Receive_IT(&huart1, (uint8_t*)bufferReceive, 1);.
Which does not wait it simply moves onward.
Next, you transmit bufferTransmit which then causes UART1 to receive one byte and continues to receive all bytes one by one in the same memory location.
It seems you are not using i properly as you probably want something like HAL_UART_Receive_IT(&huart1, (uint8_t*)&bufferReceive[i], 1);
You do not initialize anything. Peripherals, pins, clocks etc have to be set up before they can work.