blackinkgj / stm32f107-hardware-term Goto Github PK
View Code? Open in Web Editor NEWPNU 2018 Hardware Term
License: MIT License
PNU 2018 Hardware Term
License: MIT License
//초음파 센서의 핀번호를 설정한다.
int echoPin = 12;
int trigPin = 13;
void setup() {
Serial.begin(9600);
// trig를 출력모드로 설정, echo를 입력모드로 설정
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
// 초음파를 보낸다. 다 보내면 echo가 HIGH 상태로 대기하게 된다.
digitalWrite(trig, LOW);
digitalWrite(echo, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
// echoPin 이 HIGH를 유지한 시간을 저장 한다.
unsigned long duration = pulseIn(echoPin, HIGH);
// HIGH 였을 때 시간(초음파가 보냈다가 다시 들어온 시간)을 가지고 거리를 계산 한다.
float distance = ((float)(340 * duration) / 10000) / 2;
Serial.print(distance);
Serial.println("cm");
// 수정한 값을 출력
delay(500);
}
상기 아두이노 코드를 확인하면 trigger와 echo 사이에 delay가 존재함을 알 수 있습니다. 아마 우리가 0이 나온 것은 그러한 delay가 없어서 echo가 불가능 상황을 만들어서 그런 것이 아닌가도 싶습니다. 또한 duration의 크기는 약 1000 단위인 것 같아 보입니다. 위의 distance 계산은 cm 단위 계산입니다.
#include "stm32f10x.h"
#include "stm32f1xx_nucleo.h"
uint32_t TimingDelay;
void init_TIM2(void);
int main(void){
uint16_t distance;
RCC->APB2ENR = (1<<2);
GPIOA->CRH = (GPIOA->CRH&0xFFFFFF00)|(3<<0*4)|(4<<1*4); // PA8 Trig, PA9 Echo
init_TIM2();
while(1){
GPIOA->BSRR = 0x01000100;
TIM2->CNT=0; while(TIM2->CNT<12); // 12us delay
GPIOA->BSRR = 0x01000000;
while(!(GPIOA->IDR&0x0200));
TIM2->CNT=0; while(GPIOA->IDR&0x0200);
distance=(TIM2->CNT+1)/58; // cm
}
}
void init_TIM2(void){ // Output compare mode, PWM
RCC->APB1ENR |= (1<<0); // Bit 0 TIM2EN
TIM2->PSC = 72-1; // 1us
TIM2->EGR = (1<<0); // Bit 0 UG
TIM2->CR1 = (1<<0); // Bit 0 CEN
}
//---------------------------------------------------------------------------
int sigcount=0;
int t=0;
int sensor=0;
int state = 0;
void InsertSignal() {
if(t ==0) {
GPIOD->BSRRL=GPIO_Pin_0;
t = 1;
}
if(t ==1) {
GPIOD->BSRRH=GPIO_Pin_0;
int readGPIO = GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_1);
if(readGPIO != 0){
sigcount++;
state=1;
}
else if(readGPIO == 0 && state == 1) {
sensor = sigcount;
state=0;
sigcount=0;
}
}
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
InsertSignal();
}
}
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) {
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
if(state == 0 && sigcount==0) t = 0;
if(state2 == 0 && sigcount2==0) t2 = 0;
if(state3 == 0 && sigcount3==0) t3 = 0;
}
}
//--------------------------------------------------------------
GPIO_EXTILineConfig(GPIO_PortSourceGPIO0,GPIO_PinSource0);
exti.EXTI_Line = EXTI_Line0;
exti.EXTI_LineCmd = ENABLE;
exti.EXTI_Mode = EXTI_Mode_Interrupt;
exti.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_Init(&exti);
nvic_struct2.NVIC_IRQChannel = TIM4_IRQn;
nvic_struct2.NVIC_IRQChannelPreemptionPriority = 0;
nvic_struct2.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_struct2);
void TIM4_IRQHandler(void){
if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET){
sonar_start();
FLAG_ECHO = 1;
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
}
}
void EXTI0_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line0)!=RESET){
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)!=0){
TIM_SetCounter(TIM3,0);
}
if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0){
SonarValue[0] = TIM_GetCounter(TIM3);
}
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void sonar_start(){
int i;
GPIO_SetBits(GPIOB,GPIO_Pin_15);
GPIO_SetBits(GPIOB,GPIO_Pin_14);
for(i = 0; i<0x7200; i++)
;
GPIO_ResetBits(GPIOB,GPIO_Pin_15);
GPIO_ResetBits(GPIOB,GPIO_Pin_14);
}
unsigned int sonar_get(int index){
unsigned long Sonar;
Sonar = (354/2) * (unsigned long) SonarValue[index] / (72000/72);
if(Sonar > 4000)
Sonar = 4000;
if(Sonar <20)
Sonar=20;
return (unsigned int) Sonar;
}
현재의 테스트 코드에서 ultra_sensor_init()
이 사용된 곳을 전혀 찾을 수 없습니다. 이는 정상적인 동작을 보장하지 못합니다.
현재 사용하는 초음파 센서는 HC-SR04P로 HC-SR04에서의 동작은 보장 불가함을 추후 README에 작성할 것
USART에서 데이터 출력을 에서 int
형에 해당하는 내용은 아래와 같이 작성하면 될 것 같습니다.
#include<stdio.h>
#include<string.h>
void usart_send_int(int value){
char data[100];
int idx = 0;
sprintf(data, "%d", value);
for(idx = 0; idx < strlen(data); idx++){
USART_Send(USART1, data[idx]); // This is not exact
delay(...); // I think this number should be bigger than 1000
}
USART_Send(USART1, '\r');
delay(...); // I think this number should be bigger than 1000
USART_Send(USART1, '\n');
delay(...); // I think this number should be bigger than 1000
}
될지 안될지는 잘 모르겠습니다. 혹시 모르니 sprintf를 사용하지 않은 변환기도 준비 부탁드립니다!
#include "stm32f10x.h"
#include "core_cm3.h"
#include "misc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_tim.h"
#include "lcd.h"
#include "touch.h"
#define true 1
#define false 0
#define START 0
#define STOP 1
#define RESET 2
typedef int bool;
typedef struct _POINT{
uint16_t x;
uint16_t y;
}Point;
typedef struct _BUTTON{
Point pos;
bool led[4];
}Button;
bool led[4] = {false, false, false, false};
const unsigned int on[] = {
GPIO_BSRR_BS2,
GPIO_BSRR_BS3,
GPIO_BSRR_BS4,
GPIO_BSRR_BS7
};
const unsigned int off[] = {
GPIO_BSRR_BR2,
GPIO_BSRR_BR3,
GPIO_BSRR_BR4,
GPIO_BSRR_BR7
};
Point touch, pos;
Button button[4];
int flag = STOP;
int counter = 0;
int color[12] = {
// come from lcd.h
WHITE,
CYAN,
BLUE,
RED,
MAGENTA,
LGRAY,
GREEN,
YELLOW,
BROWN,
BRRED,
GRAY
};
void _RCC_Init(void);
void _GPIO_Init(void);
void _TIM_Init(void);
void _NVIC_Init(void);
void _ADC_Init(void); // DON'T USE THIS TIME
void _ADC_Start(void); // DON'T USE THIS TIME
void SetSysClock(void);
void SysInit(void);
void delay(int num){
while(num--);
}
void TIM2_IRQHandler(){
switch(flag){
case STOP:
break;
case RESET:
counter = 0;
flag = 1;
break;
case START:
default:
counter++;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
int main(){
SysInit();
SetSysClock();
_RCC_Init();
_GPIO_Init();
//_ADC_Init();
//_ADC_Start();
_NVIC_Init();
_TIM_Init();
LCD_Init();
Touch_Configuration();
Touch_Adjust();
LCD_Clear(WHITE);
{ // EXECUTION
int buttonSize = 25;
char inputString[10];
int i = 0;
int min = 0, sec = 0, msec = 0;
Point prevCirclePos = {-1, -1};
for(i = 0; i < 3; i++){
button[i].pos.x = 60*i + 50;
button[i].pos.y = 240;
LCD_DrawRectangle(60*i+50 - buttonSize, 240 - buttonSize,
60*i+50 + buttonSize, 240 + buttonSize);
switch(i){
case 0:
LCD_ShowString(60*i + 50 - buttonSize, 240, "START", BLACK, WHITE);
break;
case 1:
LCD_ShowString(60*i + 50 - buttonSize, 240, "STOP", BLACK, WHITE);
break;
case 2:
flag = RESET;
LCD_ShowString(60*i + 50 - buttonSize, 240, "RESET", BLACK, WHITE);
break;
}
}
while(1){
uint16_t input;
LCD_ShowString(1, 1, "TEAM09", BLACK, WHITE);
Touch_GetXY(&touch.x, &touch.y, 0);
// @TODO: draw rectangle change
if(T_INT == 0){
Convert_Pos(touch.x, touch.y, &pos.x, &pos.y);
sprintf(inputString, "%d\t%d", pos.x, pos.y);
LCD_ShowString(50, 50, inputString, BLACK, WHITE);
for(i = 0; i < 3; i++){
const bool isInX = button[i].pos.x - buttonSize <= pos.x
&& button[i].pos.x + buttonSize >= pos.x;
const bool isInY = button[i].pos.y - buttonSize <= pos.y
&& button[i].pos.y + buttonSize >= pos.y;
if(isInX && isInY){
switch(i){
case 0:
flag = START;
break;
case 1:
flag = STOP;
break;
case 2:
flag = RESET;
break;
}
} // end of if
} // end of for
} // end of if
min = ((counter/100)/60)%60;
sec = (counter/100)%60;
msec = (counter/10)%10; // ★★★★ this makes 10ms to 100ms ★★★★
if(msec%2)
GPIO_SetBits(GPIOD,GPIO_Pin_2);
else
GPIO_ResetBits(GPIOD,GPIO_Pin_2);
sprintf(inputString,"");
sprintf(inputString, "%4d%4d%4d", min , sec, msec);
LCD_ShowString(50, 100, inputString, BLACK, WHITE);
} // end of while
} // end of execution
}
void _RCC_Init(void){
RCC_APB1PeriphClockCmd((RCC_APB1Periph_TIM2), ENABLE);
RCC_APB2PeriphClockCmd((RCC_APB2Periph_AFIO
| RCC_APB2Periph_GPIOC
| RCC_APB2Periph_GPIOD
| RCC_APB2Periph_ADC1),ENABLE);
}
void _GPIO_Init(void){
GPIO_InitTypeDef gpio_init_struct;
gpio_init_struct.GPIO_Pin = GPIO_Pin_1;
gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
gpio_init_struct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &gpio_init_struct);
gpio_init_struct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7;
gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
gpio_init_struct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &gpio_init_struct);
GPIO_SetBits(GPIOD, GPIO_Pin_2);
}
void _TIM_Init(void){
TIM_TimeBaseInitTypeDef time_init_struct;
/// fclk = 72 MHz > STM32F10x's general clock
time_init_struct.TIM_Prescaler = 6640 - 1; // input clk speed control
time_init_struct.TIM_CounterMode = TIM_CounterMode_Up; // rising edge
time_init_struct.TIM_Period = 60 - 1; // period counting
time_init_struct.TIM_ClockDivision = TIM_CKD_DIV1;
// 1/f_clk * prescaler * period = 1/72 * 12000 * 60 = 0.01s = 1ms
TIM_TimeBaseInit(TIM2, &time_init_struct);
TIM_Cmd(TIM2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}
void _NVIC_Init(void){
NVIC_InitTypeDef nvic_init_struct;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
nvic_init_struct.NVIC_IRQChannel = TIM2_IRQn;
// Priority check
nvic_init_struct.NVIC_IRQChannelPreemptionPriority = 0x01;
nvic_init_struct.NVIC_IRQChannelSubPriority = 0x01;
nvic_init_struct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init_struct);
}
void _ADC_Init(void){
/*
ADC_InitTypeDef adc_init_struct;
ADC_DeInit(ADC1);
adc_init_struct.ADC_Mode = ADC_Mode_Independent;
adc_init_struct.ADC_ScanConvMode = DISABLE;
adc_init_struct.ADC_ContinuousConvMode = ENABLE;
adc_init_struct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
adc_init_struct.ADC_DataAlign = ADC_DataAlign_Right;
adc_init_struct.ADC_NbrOfChannel = 1;
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_239Cycles5);
ADC_Init(ADC1, &adc_init_struct);
ADC_Cmd(ADC1, ENABLE);
*/
}
void _ADC_Start(void){
/*
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
*/
}
void SysInit(void) {
/* Set HSION bit */
/* Internal Clock Enable */
RCC->CR |= (uint32_t)0x00000001; //HSION
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
RCC->CFGR &= (uint32_t)0xF0FF0000;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
}
void SetSysClock(void)
{
volatile uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while ((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 0 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
/*@TODO*/
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
/* Configure PLLs ------------------------------------------------------*/
/* PLL configuration: PLLCLK = ???? */
/*@TODO*/
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLMULL4); // CFGR_PLLMULL1 SET
/* PLL2 configuration: PLL2CLK = ???? */
/* PREDIV1 configuration: PREDIV1CLK = ???? */
/*@TODO*/
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL | RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL10 | RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5); //CFGR2 PREDIV1_2,2MUL
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while ((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
/* Select System Clock as output of MCO */
//@TODO
RCC->CFGR |= RCC_CFGR_MCO_SYSCLK;
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
지금 현재 사용하는 TIMER를 General Purpose Timer 중 가장 사용을 하지 않을 것이라 사료되는 것으로 수정 부탁드립니다. 그리고 각종 initailization에 연관된 것은 static
으로 선언을 해주시고, 각 기능은 .c
, .h
파일로 묶어 주셔서 최대한 추상화가 될 수 있도록 제작해주시길 바랍니다.
관련 참고 자료: ultasonic 브랜치의
ultrasonic.c
,ultrasonic.h
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.