mirror of
https://gitee.com/Lyon1998/pikapython.git
synced 2025-01-15 17:02:53 +08:00
197 lines
6.8 KiB
C
197 lines
6.8 KiB
C
#define USE_STDPERIPH_DRIVER
|
|
#include "stm32_p103.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
// Note that we need to multiply the period by 2 in order to work properly.
|
|
// Not sure why...
|
|
uint16_t period_value = (uint16_t) 2 * (36000000 / 65535);
|
|
|
|
/* Flag whenever the button is pressed.
|
|
* Note that the interrupt handler is initialized to only
|
|
* fire when the button is pressed, not released.
|
|
*/
|
|
uint8_t button_pressed = 0;
|
|
void EXTI0_IRQHandler(void)
|
|
{
|
|
/* Make sure the line has a pending interrupt
|
|
* (should this always be true if we are inside the interrupt handle?) */
|
|
if(EXTI_GetITStatus(EXTI_Line0) != RESET) {
|
|
button_pressed = 1;
|
|
EXTI_ClearITPendingBit(EXTI_Line0);
|
|
}
|
|
}
|
|
|
|
void TIM2_IRQHandler(void)
|
|
{
|
|
/* Note that I think we could have used TIM_GetFlagStatus
|
|
and TIM_ClearFlag instead of TIM_GetITStatus and TIM_ClearITPendingBit.
|
|
These routines seem to overlap quite a bit in functionality. */
|
|
|
|
/* Make sure the line has a pending interrupt
|
|
* which should always be true.
|
|
* */
|
|
if(TIM_GetITStatus(TIM2, USART_IT_TXE) != RESET) {
|
|
/* Toggle the LED */
|
|
GPIOC->ODR ^= 0x00001000;
|
|
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
|
}
|
|
}
|
|
|
|
/* Timer functions */
|
|
void init_timer(void) {
|
|
/* Configure peripheral clock. */
|
|
/* Let's leave PCLK1 at it's default setting of 36 MHz. */
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
|
|
|
|
/* Time base configuration */
|
|
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
|
TIM_TimeBaseStructure.TIM_Period = 5 * period_value - 1;
|
|
TIM_TimeBaseStructure.TIM_Prescaler = 65535;
|
|
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
|
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
|
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
|
|
|
|
// Enable the update interrupt
|
|
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
|
|
|
|
/* Enable the timer IRQ in the NVIC module (so that the TIM2 interrupt
|
|
* handler is enabled). */
|
|
NVIC_InitTypeDef NVIC_InitStructure;
|
|
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
|
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
|
NVIC_Init(&NVIC_InitStructure);
|
|
|
|
// Enable the timer
|
|
TIM_Cmd(TIM2, ENABLE);
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(void)
|
|
{
|
|
/* Initialization */
|
|
init_led();
|
|
|
|
init_timer();
|
|
|
|
init_button();
|
|
enable_button_interrupts();
|
|
|
|
init_rs232();
|
|
enable_rs232();
|
|
|
|
rs232_print_str("Starting...\n");
|
|
|
|
/* Infinite loop to sample timer and print results.
|
|
* There are several modes - see the README. */
|
|
int mode = 1;
|
|
uint16_t last_second_count = 0;
|
|
while(1) {
|
|
uint16_t curr_raw_count = TIM_GetCounter(TIM2);
|
|
uint16_t curr_second_count = (curr_raw_count / period_value) + 1;
|
|
|
|
// Whnever the second count changes, print a line
|
|
if(curr_second_count != last_second_count) {
|
|
rs232_print_str("MODE ");
|
|
send_number(mode, 10);
|
|
rs232_print_str(" Second Count=");
|
|
send_number(curr_second_count, 10);
|
|
rs232_print_str(" ");
|
|
rs232_print_str("Raw Count=");
|
|
send_number(curr_raw_count, 10);
|
|
rs232_print_str("\n");
|
|
last_second_count = curr_second_count;
|
|
}
|
|
|
|
// Handle special actions for modes 4 and 5.
|
|
switch(mode) {
|
|
case 4:
|
|
if(!(TIM2->CR1 & TIM_CR1_CEN)) {
|
|
rs232_print_str("Done counting up. Restarting timer...\n");
|
|
TIM_Cmd(TIM2, ENABLE);
|
|
}
|
|
break;
|
|
case 5:
|
|
if(curr_second_count == 3) {
|
|
rs232_print_str("Setting UG bit to reset count...\n");
|
|
TIM2->EGR |= 0x0001;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* A button has been pressed. Update the mode. */
|
|
if(button_pressed) {
|
|
RCC_ClocksTypeDef RCC_Clocks;
|
|
|
|
button_pressed = 0;
|
|
|
|
mode++;
|
|
if(mode > 6) {
|
|
mode = 1;
|
|
}
|
|
|
|
// Note that documentation says to disable the timer when changing
|
|
// between edge-aligned and center-aligned modes. To be safe we
|
|
// will always disable the timer when making configuration changes.
|
|
switch(mode) {
|
|
case 1:
|
|
TIM_Cmd(TIM2, DISABLE);
|
|
TIM_CounterModeConfig(TIM2, TIM_CounterMode_Up);
|
|
TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Repetitive);
|
|
TIM_Cmd(TIM2, ENABLE);
|
|
rs232_print_str("Counting up...\n");
|
|
break;
|
|
case 2:
|
|
TIM_Cmd(TIM2, DISABLE);
|
|
TIM_CounterModeConfig(TIM2, TIM_CounterMode_Down);
|
|
TIM_Cmd(TIM2, ENABLE);
|
|
rs232_print_str("Counting down...\n");
|
|
break;
|
|
case 3:
|
|
TIM_Cmd(TIM2, DISABLE);
|
|
TIM_CounterModeConfig(TIM2, TIM_CounterMode_CenterAligned1);
|
|
TIM_Cmd(TIM2, ENABLE);
|
|
rs232_print_str("Counting up/down...\n");
|
|
break;
|
|
case 4:
|
|
TIM_Cmd(TIM2, DISABLE);
|
|
// We specify to count up. However, it appears the timer
|
|
// will still count down if the timer was previously
|
|
// counting down during the last mode. Not sure why...
|
|
TIM_CounterModeConfig(TIM2, TIM_CounterMode_Up);
|
|
TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Single);
|
|
TIM_Cmd(TIM2, ENABLE);
|
|
rs232_print_str("Counting up (one shot mode)...\n");
|
|
break;
|
|
case 5:
|
|
TIM_Cmd(TIM2, DISABLE);
|
|
TIM_CounterModeConfig(TIM2, TIM_CounterMode_Up);
|
|
TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Repetitive);
|
|
TIM_Cmd(TIM2, ENABLE);
|
|
rs232_print_str("Counting up (UG bit test)...\n");
|
|
break;
|
|
case 6:
|
|
TIM_Cmd(TIM2, DISABLE);
|
|
RCC_GetClocksFreq(&RCC_Clocks);
|
|
rs232_print_str("\nMODE 4\n");
|
|
rs232_print_str("SYSCLK=");
|
|
send_number(RCC_Clocks.SYSCLK_Frequency, 10);
|
|
rs232_print_str("\n");
|
|
rs232_print_str("HCLK=");
|
|
send_number(RCC_Clocks.HCLK_Frequency, 10);
|
|
rs232_print_str("\n");
|
|
rs232_print_str("PCLK1=");
|
|
send_number(RCC_Clocks.PCLK1_Frequency, 10);
|
|
rs232_print_str("\n");
|
|
rs232_print_str("Timer Counts per Second=");
|
|
send_number(period_value, 10);
|
|
rs232_print_str("\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|