Skip to content

Instantly share code, notes, and snippets.

@Mooophy
Created October 13, 2014 00:17
Show Gist options
  • Save Mooophy/c94a703c1709537fb9e4 to your computer and use it in GitHub Desktop.
Save Mooophy/c94a703c1709537fb9e4 to your computer and use it in GitHub Desktop.
/**
*****************************************************************************
* @file main.c
* @author Yue Wang 12027710
* @version V1.0.0
* @date 22-May-2013
* @brief For the Assignment 5, 159.270 Hardware Oriented Programming.
****************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_tim.h"
#include "misc.h"
/* Macro -------------------------------------------------------------------*/
#define PWM_width uint32_t
#define Command char
#define QUEUE_SIZE 64
/**
* @brief enumeration for degrees.
*/
typedef enum
{
wy_PWM_0_DeGREE = 1000,
wy_PWM_10_DeGREE = 1111,
wy_PWM_20_DeGREE = 1222,
wy_PWM_30_DeGREE = 1333,
wy_PWM_40_DeGREE = 1444,
wy_PWM_45_DeGREE = 1500,
wy_PWM_50_DeGREE = 1556,
wy_PWM_60_DeGREE = 1667,
wy_PWM_70_DeGREE = 1778,
wy_PWM_80_DeGREE = 1889,
wy_PWM_90_DeGREE = 2000,
} wy_PWM_WiDTH_TypeDef ;
/**
* @brief buffer for UART.
*/
typedef struct Queue
{
char a[QUEUE_SIZE];
int start;
int end;
} Queue;
/**
* @brief Global variables.
*/
Queue RXQ, TXQ;
/* Prototype------------------------------------------------------------------*/
void wy_PWM_handle (wy_PWM_WiDTH_TypeDef _w);
void wy_Initialize (void);
void wy_WindScreen (void);
void wy_CommandHandle(Command _c);
void uart_putchar (char c);
int is_uart_data_ready(void);
char uart_getchar (void);
void delay_millisec (register unsigned short n);
/* Main ------------------------------------------------------------------*/
int main(void)
{
wy_Initialize();
while (1)
{
if (is_uart_data_ready())
{
Command c = uart_getchar();
wy_CommandHandle(c);
uart_putchar(c);
}
}
}
/* Function definitions ------------------------------------------------------*/
/**
* @brief USART handler.
*/
void USART1_IRQHandler(void)
{
//was it a receive interrupt?
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
char c = (USART1->DR & 0xff);
if ((RXQ.end+1)%QUEUE_SIZE != RXQ.start)
{
RXQ.a[RXQ.end] = c;
RXQ.end = (RXQ.end + 1)%QUEUE_SIZE;
}
}
//was it a transmit interrupt?
if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
{
if (TXQ.start != TXQ.end)
{
USART1->DR = TXQ.a[TXQ.start];
TXQ.start = (TXQ.start + 1)%QUEUE_SIZE;
}
else
{
USART1->CR1 &= ~USART_CR1_TXEIE; //disable interrupt
}
}
}
/**
* @brief Initialization for everything to be used.
*/
void wy_Initialize(void)
{
/*RCC */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 , ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6 , ENABLE);
/*GPIO*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
/*PWM */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*RXD */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA9 <--->RXD blue
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*TXD */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10 <--->TXD green
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*USART*/
USART_InitTypeDef USART_InitStructure;
USART_StructInit(&USART_InitStructure);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
USART1->CR1 |= USART_CR1_RXNEIE; //enable Received data interrupt
/*NVIC*/
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*TIM4*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 24 - 1;
TIM_TimeBaseStructure.TIM_Period = 20000 - 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
/*CH3*/
TIM_OCInitTypeDef TIM_OCStructure;
TIM_OCStructInit(&TIM_OCStructure);
TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OC3Init(TIM4, &TIM_OCStructure);
TIM_Cmd(TIM4, ENABLE);
}
/**
* @brief output to PUTTY.
*/
void uart_putchar(char c)
{
if ((TXQ.end+1)%QUEUE_SIZE != TXQ.start)
{
TXQ.a[TXQ.end] = c;
TXQ.end = (TXQ.end + 1)%QUEUE_SIZE;
}
if (! (USART1->CR1&USART_CR1_TXEIE))
{ //ie the tx buffer is empty
USART1->CR1 |= USART_CR1_TXEIE; //enable transmit interrupt
}
}
/**
* @brief check if new data have arrived.
*/
int is_uart_data_ready(void)
{
return (RXQ.start != RXQ.end);
}
/**
* @brief collect new character, write into c and return it.
*/
char uart_getchar(void)
{
char c = RXQ.a[RXQ.start];
RXQ.start = (RXQ.start + 1)%QUEUE_SIZE;
return c;
}
/**
* @brief set pulse width.
*/
void wy_PWM_handle (wy_PWM_WiDTH_TypeDef _w)
{
TIM_SetCompare3(TIM4, _w);
}
/**
* @brief handle command by calling relevant functions.
*/
void wy_CommandHandle(Command _c)
{
switch (_c)
{
case '0' : wy_PWM_handle(wy_PWM_0_DeGREE );
break;
case '1' : wy_PWM_handle(wy_PWM_10_DeGREE );
break;
case '2' : wy_PWM_handle(wy_PWM_20_DeGREE );
break;
case '3' : wy_PWM_handle(wy_PWM_30_DeGREE );
break;
case '4' : wy_PWM_handle(wy_PWM_40_DeGREE );
break;
case '5' : wy_PWM_handle(wy_PWM_50_DeGREE );
break;
case '6' : wy_PWM_handle(wy_PWM_60_DeGREE );
break;
case '7' : wy_PWM_handle(wy_PWM_70_DeGREE );
break;
case '8' : wy_PWM_handle(wy_PWM_80_DeGREE );
break;
case '9' : wy_PWM_handle(wy_PWM_90_DeGREE );
break;
case 'n' : wy_PWM_handle(wy_PWM_45_DeGREE );
break;
case 'N' : wy_PWM_handle(wy_PWM_45_DeGREE );
break;
case 'w' : wy_WindScreen();
break;
case 'W' : wy_WindScreen();
break;
}
}
/**
* @brief move the arm back and forth continuously.
*/
void wy_WindScreen (void)
{
int cmd=1000;
wy_PWM_handle(wy_PWM_0_DeGREE);
delay_millisec(400);
while(! is_uart_data_ready())
{
while( (cmd<2000) & (! is_uart_data_ready()))
{
wy_PWM_handle(cmd);
delay_millisec(10);
cmd += 10 ;
}
while( (cmd>1000) & (! is_uart_data_ready()))
{
wy_PWM_handle(cmd);
delay_millisec(10);
cmd -= 10 ;
}
}
}
/**
* @brief millisecond delay.
*/
void delay_millisec(register unsigned short n)
{
if (n > 5) n -= 5;
else n = 1;
TIM6->PSC = 23999;
TIM6->ARR = n;
TIM6->CNT = 0;
TIM6->EGR = TIM_EGR_UG;
TIM6->CR1 |= (TIM_CR1_OPM | TIM_CR1_CEN);
while (TIM6->CR1 & TIM_CR1_CEN);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment