Bir önceki konumuz GPIO olduğuna göre şimdi beeplemeye başlayabiliriz :).
MCU ile tanışırken de değindiğim beep birimini kullanarak devresiz buzzer çalıştıracağız. STM8S103 MCU’nun PD4 pinindeki birim bizim için 1KHz, 2KHz ve 4KHz değerlerinde sabit frekans çıkışı sağlar. Bizde ilgili Registerları kullanarak düdüğümüzü öttürürüz 🙂
Peki işin arka tarafında neler oluyor?
Öncelikle Beep blok diyagramını inceleyelim.

Görüldüğü gibi BEEP birimi osilatör kaynağı olarak iki seçenek kabul eder. Bunlardan birisi HSE diğeri ise LSI. Ne olacaktı yani harici kristal osilatör kullanmıyorsak düdük öttüremeyecekmiydik. Elbette öttürürüz. Bunun için LSI RC osilatör kaynağını kullanacağız. Reference Manuel LSI osilatör kaynağı kullanılacaksa düzgün bir frekans elde etmek için LSI kaynağının ölçülerek kalibre edilmesini tavsiye eder. Sebebi ise LSI 128KHz osilatör kaynağının çalışma sıcaklığı limitleri dahilinde çıkış frekansının +/-12,5% tölerans ile değişiklik gösterebilmesidir. Bu kalibre işlemi için kütüphanede var olan BEEP_LSICalibrationConfig fonksiyonunun içerisine harici olarak LSIMeasurment() fonksiyonunu kendimiz ekleyeceğiz ve iç içe döngü ile kalibrasyon olayını halletmiş olacağız. Aşağıda ekleyeceğimiz fonksiyonu paylaşacağım.
Değinmek istediğim bir diğer konu ise kalibrasyon işlemi sırasında bir TIMER kullanılıyor. Bunun ayrıntılarına bilmemize gerek yok fonksiyon olayı kendisi hallediyor fakat genede bunu bilmekte fayda var. Fonksiyon içerisinde kullanılan MCU’ya göre gerekli TIMER birimini aktif ediyor(STM8S103 için TIMER1) ve gerekli ölçümü yaptıktan sonra ilgili TIMER devre dışı bırakılıyor. Hangi TIMER’ı kullandığı hususuna uygulama videosunda değineceğim.
Dolayısıyla ileride projelerde TIMER1 ve Beep kullanacaksak LSI osilatör kaynağını kalibre ettikten sonra TIMER1’i kurma konusuna dikkat etmeliyiz. Kafaları fazla karıştırmadım umarım….
Kalibrasyon işleminden sonra kullanacağımız frekansı seçerek BEEPEN bitini SET ederek sinyal çıkışını elde ediyoruz.
Şimdi kütüphanedeki kodları inceleyelim.
#include "stm8s_beep.h"
ile kütüphaneyi dahil ettik.
Kullanacağımız osilatör kaynağına ek olarak CLK_LSICmd() fonksiyonunuda ENABLE ettik.
void BEEP_DeInit(void)
Fonksiyonunu resetleme işlemi için kullanıyoruz.
void BEEP_Init(BEEP_Frequency_TypeDef BEEP_Frequency)
Fonksiyonu ile kullanacağımız frekansı aşağıdaki parametreleri kullanarak seçiyoruz.
typedef enum {
BEEP_FREQUENCY_1KHZ = (uint8_t)0x00, /*!< Beep signal output frequency equals to 1 KHz */
BEEP_FREQUENCY_2KHZ = (uint8_t)0x40, /*!< Beep signal output frequency equals to 2 KHz */
BEEP_FREQUENCY_4KHZ = (uint8_t)0x80 /*!< Beep signal output frequency equals to 4 KHz */
} BEEP_Frequency_TypeDef;
void BEEP_LSICalibrationConfig(uint32_t LSIFreqHz)
Fonksiyonu LSI kaynağını kalibre için 32 bitlik tam sayı girilmesini ister. Bizim ekleme yapacağımız LSIMeasurment() fonksiyonu bu 32 bitlik parametrenin yerine gelecektir.
/**
* @brief Measure the LSI frequency using timer IC1 and update the calibration registers.
* @note It is recommended to use a timer clock frequency of at least 10MHz in order
* to obtain a better in the LSI frequency measurement.
* @param None
* @retval None
*/
uint32_t LSIMeasurment(void)
{
uint32_t lsi_freq_hz = 0x0;
uint32_t fmaster = 0x0;
uint16_t ICValue1 = 0x0;
uint16_t ICValue2 = 0x0;
/* Get master frequency */
fmaster = CLK_GetClockFreq();
/* Enable the LSI measurement: LSI clock connected to timer Input Capture 1 */
AWU->CSR |= AWU_CSR_MSR;
#if defined (STM8S903) || defined (STM8S103) || defined (STM8S003) || defined (STM8S001)
/* Measure the LSI frequency with TIMER Input Capture 1 */
/* Capture only every 8 events!!! */
/* Enable capture of TI1 */
TIM1_ICInit(TIM1_CHANNEL_1, TIM1_ICPOLARITY_RISING, TIM1_ICSELECTION_DIRECTTI, TIM1_ICPSC_DIV8, 0);
/* Enable TIM1 */
TIM1_Cmd(ENABLE);
/* wait a capture on cc1 */
while((TIM1->SR1 & TIM1_FLAG_CC1) != TIM1_FLAG_CC1);
/* Get CCR1 value*/
ICValue1 = TIM1_GetCapture1();
TIM1_ClearFlag(TIM1_FLAG_CC1);
/* wait a capture on cc1 */
while((TIM1->SR1 & TIM1_FLAG_CC1) != TIM1_FLAG_CC1);
/* Get CCR1 value*/
ICValue2 = TIM1_GetCapture1();
TIM1_ClearFlag(TIM1_FLAG_CC1);
/* Disable IC1 input capture */
TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1E);
/* Disable timer2 */
TIM1_Cmd(DISABLE);
#else
/* Measure the LSI frequency with TIMER Input Capture 1 */
/* Capture only every 8 events!!! */
/* Enable capture of TI1 */
TIM3_ICInit(TIM3_CHANNEL_1, TIM3_ICPOLARITY_RISING, TIM3_ICSELECTION_DIRECTTI, TIM3_ICPSC_DIV8, 0);
/* Enable TIM3 */
TIM3_Cmd(ENABLE);
/* wait a capture on cc1 */
while ((TIM3->SR1 & TIM3_FLAG_CC1) != TIM3_FLAG_CC1);
/* Get CCR1 value*/
ICValue1 = TIM3_GetCapture1();
TIM3_ClearFlag(TIM3_FLAG_CC1);
/* wait a capture on cc1 */
while ((TIM3->SR1 & TIM3_FLAG_CC1) != TIM3_FLAG_CC1);
/* Get CCR1 value*/
ICValue2 = TIM3_GetCapture1();
TIM3_ClearFlag(TIM3_FLAG_CC1);
/* Disable IC1 input capture */
TIM3->CCER1 &= (uint8_t)(~TIM3_CCER1_CC1E);
/* Disable timer3 */
TIM3_Cmd(DISABLE);
#endif /* (STM8S903) || (STM8S103) || (STM8S003) || (STM8S001) */
/* Compute LSI clock frequency */
lsi_freq_hz = (8 * fmaster) / (ICValue2 - ICValue1);
/* Disable the LSI measurement: LSI clock disconnected from timer Input Capture 1 */
AWU->CSR &= (uint8_t)(~AWU_CSR_MSR);
return (lsi_freq_hz);
}
Buradan sonra kullandığımız buzzerın datasheetine göre kullanadığımız frekansı seçmek. Benim uygulama kullanacağım buzzer için bilgiler şu şekilde.

Ayrıca dosyayı buradan indirebilirsiniz.
/**
******************************************************************************
* @file Project/main.c
* @author N7A TECHNIC
* @brief Main program body
******************************************************************************
* www.n7a.web.tr
******************************************************************************
*/
/*
PD4->Devresiz Buzzer
PD5->Devreli Buzzer
PD3->1KHz Butonu
PD2->2KHz Butonu
PD1->4KHz Butonu
PC7->Devreli Buzzer Butonu
*/
/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
#include "stm8s_clk.h"
#include "stm8s_gpio.h"
#include "stm8s_beep.h"
/* Private defines -----------------------------------------------------------*/
#define beepOut GPIOD,GPIO_PIN_4
#define dBuzzerOut GPIOD,GPIO_PIN_5
#define b1KHz GPIOD,GPIO_PIN_3
#define b2KHz GPIOD,GPIO_PIN_2
#define b4KHz GPIOD,GPIO_PIN_1
#define bDevBuzzer GPIOC,GPIO_PIN_7
#define LED GPIOB,GPIO_PIN_5
/* Private function prototypes -----------------------------------------------*/
uint32_t LSIMeasurment(void);
/* Private functions ---------------------------------------------------------*/
void main(void)
{
/* Infinite loop */
CLK_DeInit();
CLK_HSECmd(DISABLE);
CLK_LSICmd(ENABLE);
CLK_HSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY)==0);
CLK_ClockSwitchCmd(ENABLE);
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
GPIO_Init(dBuzzerOut,GPIO_MODE_OUT_PP_LOW_FAST);
GPIO_Init(b1KHz,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(b2KHz,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(b4KHz,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(bDevBuzzer,GPIO_MODE_IN_PU_NO_IT);
GPIO_Init(LED,GPIO_MODE_OUT_OD_HIZ_FAST);
BEEP_DeInit();
BEEP_LSICalibrationConfig(LSIMeasurment());
BEEP_Cmd(DISABLE);
while (1)
{
if(GPIO_ReadInputPin(b1KHz)==0)
{
GPIO_WriteLow(dBuzzerOut);
BEEP_Init(BEEP_FREQUENCY_1KHZ);
BEEP_Cmd(ENABLE);
GPIO_WriteLow(LED);
}
else
{
if(GPIO_ReadInputPin(b2KHz)==0)
{
GPIO_WriteLow(dBuzzerOut);
BEEP_Init(BEEP_FREQUENCY_2KHZ);
BEEP_Cmd(ENABLE);
GPIO_WriteLow(LED);
}
else
{
if(GPIO_ReadInputPin(b4KHz)==0)
{
GPIO_WriteLow(dBuzzerOut);
BEEP_Init(BEEP_FREQUENCY_4KHZ);
BEEP_Cmd(ENABLE);
GPIO_WriteLow(LED);
}
else
{
if(GPIO_ReadInputPin(bDevBuzzer)==0)
{
BEEP_Cmd(DISABLE);
GPIO_WriteHigh(dBuzzerOut);
GPIO_WriteLow(LED);
}
else
{
GPIO_WriteHigh(LED);
}
}
}
}
}
}
/**
* @brief Measure the LSI frequency using timer IC1 and update the calibration registers.
* @note It is recommended to use a timer clock frequency of at least 10MHz in order
* to obtain a better in the LSI frequency measurement.
* @param None
* @retval None
*/
uint32_t LSIMeasurment(void)
{
uint32_t lsi_freq_hz = 0x0;
uint32_t fmaster = 0x0;
uint16_t ICValue1 = 0x0;
uint16_t ICValue2 = 0x0;
/* Get master frequency */
fmaster = CLK_GetClockFreq();
/* Enable the LSI measurement: LSI clock connected to timer Input Capture 1 */
AWU->CSR |= AWU_CSR_MSR;
#if defined (STM8S903) || defined (STM8S103) || defined (STM8S003) || defined (STM8S001)
/* Measure the LSI frequency with TIMER Input Capture 1 */
/* Capture only every 8 events!!! */
/* Enable capture of TI1 */
TIM1_ICInit(TIM1_CHANNEL_1, TIM1_ICPOLARITY_RISING, TIM1_ICSELECTION_DIRECTTI, TIM1_ICPSC_DIV8, 0);
/* Enable TIM1 */
TIM1_Cmd(ENABLE);
/* wait a capture on cc1 */
while((TIM1->SR1 & TIM1_FLAG_CC1) != TIM1_FLAG_CC1);
/* Get CCR1 value*/
ICValue1 = TIM1_GetCapture1();
TIM1_ClearFlag(TIM1_FLAG_CC1);
/* wait a capture on cc1 */
while((TIM1->SR1 & TIM1_FLAG_CC1) != TIM1_FLAG_CC1);
/* Get CCR1 value*/
ICValue2 = TIM1_GetCapture1();
TIM1_ClearFlag(TIM1_FLAG_CC1);
/* Disable IC1 input capture */
TIM1->CCER1 &= (uint8_t)(~TIM1_CCER1_CC1E);
/* Disable timer2 */
TIM1_Cmd(DISABLE);
#else
/* Measure the LSI frequency with TIMER Input Capture 1 */
/* Capture only every 8 events!!! */
/* Enable capture of TI1 */
TIM3_ICInit(TIM3_CHANNEL_1, TIM3_ICPOLARITY_RISING, TIM3_ICSELECTION_DIRECTTI, TIM3_ICPSC_DIV8, 0);
/* Enable TIM3 */
TIM3_Cmd(ENABLE);
/* wait a capture on cc1 */
while ((TIM3->SR1 & TIM3_FLAG_CC1) != TIM3_FLAG_CC1);
/* Get CCR1 value*/
ICValue1 = TIM3_GetCapture1();
TIM3_ClearFlag(TIM3_FLAG_CC1);
/* wait a capture on cc1 */
while ((TIM3->SR1 & TIM3_FLAG_CC1) != TIM3_FLAG_CC1);
/* Get CCR1 value*/
ICValue2 = TIM3_GetCapture1();
TIM3_ClearFlag(TIM3_FLAG_CC1);
/* Disable IC1 input capture */
TIM3->CCER1 &= (uint8_t)(~TIM3_CCER1_CC1E);
/* Disable timer3 */
TIM3_Cmd(DISABLE);
#endif /* (STM8S903) || (STM8S103) || (STM8S003) || (STM8S001) */
/* Compute LSI clock frequency */
lsi_freq_hz = (8 * fmaster) / (ICValue2 - ICValue1);
/* Disable the LSI measurement: LSI clock disconnected from timer Input Capture 1 */
AWU->CSR &= (uint8_t)(~AWU_CSR_MSR);
return (lsi_freq_hz);
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval : None
*/
void assert_failed(u8* file, u32 line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/