- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
i have four switches attached to 4 input pins with resistive pull ups in a CY8CKIT-059 PSoC 5LP
pressing a switch or releasing a switch causes an interrupt that saves the time according to a
fixed function counter, 16 bit (interrupt occurs on rising and falling edges)
the interrupt routine writes a variety of information to a character LCD display
including which pin (switch) was pushed or released, how many datum have been recorded,
and the recorded data
after programming or after reset (switch on kit-059) the display shows "release"
but "release" is written to the display only on a rising edge (switch release) interrupt
in addition, count start command (API) is supposed to happen on first switch activation (regardless of switch)
but it appears to start immediately
also, if one waits a while before pressing a switch, it is clear that the counter has counted (is not at max count)
hence it looks like the interrupt service routine is run once before any switches are pressed
why is that happening and what can i do about it?
archive bundle attached
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
to BoTa: I will look into ButtonSw32
to Noriaki Tanaka and Motoo Tanaka:
I tried your suggestions
I ended up with
isr_1_ClearPending();
InPin_ClearInterrupt();
isr_1_StartEx(PinISRHandler);
isr_1_ClearPending();
removing any of the clear statements did not solve my issue
Ii appears I need all three
to Motoo Tanaka:
Thank you for the re-write. I will follow your suggestion
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
LaAd,
I may suggest using an existing switch-button library, which handles button press and release events with debouncing
ButtonSw32: button switch debouncer component
/odissey1
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please try isr_1_ClearPending(); after isr_1_StartEx(PinISRHandler);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I think that I'd like to call
isr_1_ClearPending() ;
and
InPin_ClearInterrupt();
before calling
isr_1_StartEx(PinISRHandler) ;
But as far as they are before "CyGlobalIntEnable ;" it may be OK.
And also I'd like to place following lines before "for (;;) " loop
================
//Set up interrupt and set address as the ISR vector for the interrupt.
isr_1_StartEx(PinISRHandler);
CyGlobalIntEnable;
================
And (sorry for being too picky), I'd suggest you not to place
LCD_Position() and/or LCD_PrintString() inside ISR.
In the ISR, just set flags to notify the main (or foreground) task
to take care of such time consuming procedures.
So I tried to modify your main.c like below, may be I'm mis-understanding the logic though.
====================
/*******************************************************************************
* File Name: main.c
* Pandrol / Vortok USA
* 5688 Tec Drive
* Avon New York 14414
* L M Adelson
* July 2 2019
*
* Version: 1.0
*
* Description:
* This project writes text to a 4x20 LCD display
* The operating device is PSoC CY8CKIT-059
* The processor is CY8C5888LTI-LP097
* The operating LCD Display is a Crystalfontz America CFAH2004A-TMI-JT
* The processor communcates to the LCD in parallel using a 4 bit interface
* Two switches are operated via interrupt to change the display
*
*******************************************************************************/
#include <project.h>
/*******************************************************************************
* Function Name: main
********************************************************************************
*
* Summary:
* The main program does the following
* 1. Initializes the LCD.
* 2. Writes text to each of 4 lines of display.
* 3. waits for interrupt from 4 inputs indicating a change of state
* either a switch is pushed (pin goes low) or released (pin goes high)
* don't know what order push / release will be
* first push starts timer and records time
* subsequent push or release cause time to be recorded in appropriate memory
* after 8 data recorded, write all 8 dataum to LCD as:
* push switch 1 release switch 4
* push switch 2 release switch 4
* push switch 3 release switch 4
* push switch 4 release switch 4
*
* CAVEAT: if you write more than 20 charaters, it does a cr lf lf
* so the line continues with a skipped line
* anything on that line gets overwritten
*
* Parameters:
* None.
*
* Return:
* None.
*
*******************************************************************************/
// initialize parameters
uint8 pos = 0u; // column of LCD dispaly to wrtie in
uint8 row = 0u; // row of LCD dispaly to wrtie in
uint8 count = 0u; // count how many times get an interrunpt
uint8 pin_stat = 0u; // read interrupt vector value (stat for status)
uint8 last_pin_stat = 0u; // pin status before present switch operation
uint8 change_pin_stat = 0u; // changed in pin status - i.e. which switch
uint8 mode = 0u; // counter for how many interrupts seen
int counts[20]; // variable to store counts
int num = 0; // temp variable
uint8 i; // index variable for loops
uint8 press_release_flag = 0; // 0 is false for release 1 is true for press
volatile int intr_flag = 0 ; // <-- added
volatile int pin_changed_flag = 0 ; // <-- added
// interupt prototype delcaration
// PinISRHandler is routine when get pin interrupt
CY_ISR_PROTO(PinISRHandler);
void report_mode(void) ; // <-- added
int main()
{
LCD_Start() ;
/* Clear pin Interrupt */
InPin_ClearInterrupt();
isr_1_ClearPending() ;
//Set up interrupt and set address as the ISR vector for the interrupt.
isr_1_StartEx(PinISRHandler) ;
CyGlobalIntEnable;
for(;;)
{
CyDelay(2000); //pause
mode = 0;
{
while (mode < 😎 //mode specifies number of edges detected
{} //start with 0, end after 4 switches or
//at 8 transitions
for (i = 0; i < 4; i++) //clear screen
{
LCD_Position(i, 0);
LCD_PrintString(" ");
}
for (i = 0; i < 19; i++)
{
if (counts == 0) counts = 65535;
}
if (intr_flag) {
intr_flag = 0 ;
if (press_release_flag) {
LCD_Position(0, 0);
LCD_PrintString(" push ");
} else {
LCD_Position(0, 0);
LCD_PrintString(" release ");
}
if (pin_changed_flag) {
pin_changed_flag = 0 ;
report_mode() ;
}
}
//write output to LCD
LCD_Position(0, 0);
LCD_PrintU32Number(counts[1]);
LCD_Position(0, 8);
LCD_PrintU32Number(counts[11]);
LCD_Position(1, 0);
LCD_PrintU32Number(counts[2]);
LCD_Position(1, 8);
LCD_PrintU32Number(counts[12]);
LCD_Position(2, 0);
LCD_PrintU32Number(counts[4]);
LCD_Position(2, 8);
LCD_PrintU32Number(counts[14]);
LCD_Position(3, 0);
LCD_PrintU32Number(counts[8]);
LCD_Position(3, 8);
LCD_PrintU32Number(counts[18]);
mode = 0;
Counter_Stop();
Counter_WriteCounter(0); //reset to full count via rollover
}
}
}
/*******************************************************************************
* Function Name: PinISRHandler
********************************************************************************
*
* Summary:
* This subroutine handles the interrupts
1. Initializes the LCD.
* 2. Writes text to each of 4 lines of display.
*
* CAVEAT: if you write more than 20 charaters, it does a cr lf lf
* so the line continues with a skipped line
* anything on that line gets overwritten
*
* Parameters:
* None.
*
* Return:
* None.
*
*******************************************************************************/
CY_ISR(PinISRHandler)
{
num = Counter_ReadCounter();
pin_stat = InPin_Read();
if (mode == 0)
{
Counter_Start();
last_pin_stat = 0;
}
if (pin_stat > last_pin_stat)
{
change_pin_stat = pin_stat - last_pin_stat;
press_release_flag = 1; // 0 is false for release 1 is true for press
}
else
{
change_pin_stat = last_pin_stat - pin_stat;
press_release_flag = 0; // 0 is false for release 1 is true for press
}
/* Clear pending Interrupt */
isr_1_ClearPending();
/* Clear pin Interrupt */
InPin_ClearInterrupt();
/* what changed? */
if (press_release_flag) //here for switch pushed // 0 is false for release 1 is true for press
{
counts[change_pin_stat] = num;
// LCD_Position(0, 0);
// LCD_PrintString(" push ");
}
if (! press_release_flag) //here for switch released // 0 is false for release 1 is true for press
{
counts[change_pin_stat + 10] = num;
// LCD_Position(0, 0);
// LCD_PrintString(" release ");
}
if (last_pin_stat != pin_stat) // take care of change condition
{
pin_changed_flag = 1 ;
/*
LCD_Position(1, 0);
LCD_PrintString("mode ");
LCD_PrintNumber(mode);
LCD_PrintString(" ");
LCD_PrintString("pin ");
LCD_PrintNumber(pin_stat);
LCD_PrintString(" ");
LCD_Position(2,0);
LCD_PrintString("last ");
LCD_PrintNumber(last_pin_stat);
LCD_PrintString(" ");
LCD_PrintString("change ");
LCD_PrintNumber(change_pin_stat);
LCD_PrintString(" ");
LCD_Position(3, 0);
LCD_PrintString(" counts ");
LCD_PrintNumber(num);
LCD_PrintString(" ");
*/
mode = mode + 1;
last_pin_stat = pin_stat;
}
if (mode > 😎
{
Counter_Stop();
Counter_Init();
}
}
void report_mode(void)
{
LCD_Position(1, 0);
LCD_PrintString("mode ");
LCD_PrintNumber(mode);
LCD_PrintString(" ");
LCD_PrintString("pin ");
LCD_PrintNumber(pin_stat);
LCD_PrintString(" ");
LCD_Position(2,0);
LCD_PrintString("last ");
LCD_PrintNumber(last_pin_stat);
LCD_PrintString(" ");
LCD_PrintString("change ");
LCD_PrintNumber(change_pin_stat);
LCD_PrintString(" ");
LCD_Position(3, 0);
LCD_PrintString(" counts ");
LCD_PrintNumber(num);
LCD_PrintString(" ");
}
/* [] END OF FILE */
====================
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
to BoTa: I will look into ButtonSw32
to Noriaki Tanaka and Motoo Tanaka:
I tried your suggestions
I ended up with
isr_1_ClearPending();
InPin_ClearInterrupt();
isr_1_StartEx(PinISRHandler);
isr_1_ClearPending();
removing any of the clear statements did not solve my issue
Ii appears I need all three
to Motoo Tanaka:
Thank you for the re-write. I will follow your suggestion