STM8L051F3基礎功能:內部時鍾;TIM2定時器;串口及printf;


STM8L051調試筆記之基礎功能:

系統時鍾、串口、定時器都是基礎而且必須的功能,這里放在一起統一記錄,之所以用TIM2定時器,是因為想實現STM32的滴答定時器功能

這些基礎功能沒什么好理解的,就直接貼代碼了main.c:

main.c:

  void main(void)
  {
    enableInterrupts();
    Sysclk_Init();
    LED_Init();
    Uart1_Init();
  
    
    printf("This is a STM8 code!!!\r\n");
   
   
   while (1)
   {
     
     if(secondClock_flag)
     {
       secondClock_flag = 0;
       printf("This is a STM8 code!!!\r\n");
     }
     
     if(calculate_flag)
     {
       calculate_flag = 0;
       printf("a minute\r\n");
     }
   }
}

內部時鍾及定時器:

我使用的板子上是沒有外部晶振的,所以這里使用的是內部16Mhz的晶振,可以按個人需求對其進行分頻。需要說明的是,STM8的程序中,即使沒有配置系統時鍾,板子依然可以工作,因為默認會有一個2Mhz的內部時鍾,這一點在手冊中可以查到:

接下來貼代碼,由於本人比較懶,只保留的內部時鍾的代碼,對時鍾要求不高的可以參考參考,要求時鍾准確的還是用外部晶振吧,代碼中附送延時函數,在我的上一篇筆記中有記錄

sysclk.c:

#include "sysclk.h"

volatile u8 fac_us=0;

u8 secondClock_flag = 0;
u8 calculate_flag = 0;

void delay_us(u16 nus)
{
  __asm(
"PUSH A          \n"
"DELAY_XUS:      \n"
"LD A,fac_us     \n"
"DELAY_US_1:     \n"
"NOP             \n"
"DEC A           \n"
"JRNE DELAY_US_1 \n"
"NOP             \n"
"DECW X          \n"
"JRNE DELAY_XUS  \n"
"POP A           \n"
); 
}

void delay_ms(u32 nms)
{
  u8 t;
  if(nms>65)
  {
    t=nms/65;
    while(t--)delay_us(65000);
    nms=nms%65;
  }
  delay_us(nms*1000);
}

void delay_init(u8 clk)
{
  if(clk>16)fac_us=(16-4)/4;
  else if(clk>4)fac_us=(clk-4)/4; 
  else fac_us=1;
}

void TIM2_Init(void)
{
  CLK_PeripheralClockConfig(CLK_Peripheral_TIM2,ENABLE);
  TIM2_TimeBaseInit(TIM2_Prescaler_16,TIM2_CounterMode_Up,1000);  //將系統時鍾16分頻得到1Mhz,計數1000(或999,未細究)則得到一個每ms進一次的中斷,
  TIM2_ARRPreloadConfig(ENABLE);
  TIM2_ITConfig(TIM2_IT_Update,ENABLE);
  
  TIM2_Cmd(ENABLE);
}

void Sysclk_Init(void)
{
  CLK_HSICmd(ENABLE);
  CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);  //選擇HIS內部晶振,
  CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);  //STM8,HSI為16Mhz,這里1分頻即不分頻
  
  TIM2_Init();
  delay_init(16);  //參數是系統時鍾,這里是16Mhz所以參數為16
}

sysclk.h中內容:

中斷stm8l15x_it.c中內容(找到TIM2定時器對應的INTERRUPT_HANDLER):

串口功能:

這里使用的是PA2,PA3兩個腳的串口,由於STM8只有8kb的flash,使用printf函數時一不小心就內存不足了,也在網上嘗試了很多解決方案,這里我嘗試的比較有用的方法是在設置里將printf formatter的值改為Tiny,我這里改為small也是可以的,至於這樣會產生什么影響需要再進行分析了,聽說改為Tiny是不使用對浮點數的操作,會使對printf相關庫函數編譯的代碼小很多,具體是否如此沒有驗證,如有錯誤誤導他人請及時批評指正。

貼代碼:

uart.c

#include "uart.h"

/**
  * @brief  Configure USART peripheral  
  * @param  None
  * @retval None
  */
void Uart1_Init(void)
{
  /* USART1 configured as follow:
        - BaudRate = 115200 baud  
        - Word Length = 8 Bits
        - One Stop Bit
        - Odd parity
        - Receive and transmit enabled
        - USART Clock disabled
  */
  /* Enable USART clock */
  CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);
  
  /* USART1 Tx- Rx remapping to PA2- PA3 */
  SYSCFG_REMAPDeInit();
  SYSCFG_REMAPPinConfig(REMAP_Pin_USART1TxRxPortA, ENABLE);
  
  /* Configure USART Tx pin output*/
  GPIO_Init(GPIOA, GPIO_Pin_2, GPIO_Mode_Out_PP_High_Fast);
  
  /* Configure USART Rx pin input*/
  GPIO_Init(GPIOA, GPIO_Pin_3, GPIO_Mode_In_PU_No_IT);
  
  /* RESET USART1 */
  USART_DeInit(USART1);
  
  /* USART configuration */
  USART_Init(USART1, (u32)115200, USART_WordLength_8b, USART_StopBits_1, USART_Parity_No, USART_Mode_Tx|USART_Mode_Rx);

  /* Enable the USART Receive interrupt: this interrupt is generated when the USART
    receive data register is not empty */
  USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  /* Enable the USART Transmit complete interrupt: this interrupt is generated when the USART
    transmit Shift Register is empty */
  //USART_ITConfig(EVAL_COM1, USART_IT_TC, ENABLE);

  /* Enable USART */
  USART_Cmd(USART1, ENABLE);
}

/* 發送一個字節 */
void UART1_SendByte(u8 data)
{
  USART_SendData8(USART1, data);
  
  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}

/* 發送len個字符 */
void UART1_SendStr(u8 *str)
{
  while(*str != '\0')    
  {    
    UART1_SendByte(*str++);
  }    
}

/* 接收一個字符 */
u8 UART1_ReceiveByte(void)
{
  u8 UART1_RX_BUF; 
      
  while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
  
  UART1_RX_BUF = USART_ReceiveData8(USART1);
  
  return  UART1_RX_BUF;
}

#ifdef _IAR_
int fputc(int ch, FILE *f)
{
  UART1_SendByte(ch);
  return (ch);
}
#else
PUTCHAR_PROTOTYPE
{
  UART1_SendByte(c);
  return (c);
}
#endif

GETCHAR_PROTOTYPE
{
#ifdef _COSMIC_
   char c = 0;
#else
   int c = 0;
#endif
   /* Loop until the Read data register flag is SET */
   while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
   c = USART_ReceiveData8(USART1);
   return (c);
}

uart.h:

#ifndef __UART_H
#define __UART_H

/* 包含系統頭文件 */
#include "stm8l15x_conf.h"
#include <stdio.h>
#include <stdarg.h>

/* Private define ------------------------------------------------------------*/
#ifdef _RAISONANCE_
#define PUTCHAR_PROTOTYPE int putchar (char c)
#define GETCHAR_PROTOTYPE int getchar (void)
#elif defined (_COSMIC_)
#define PUTCHAR_PROTOTYPE char putchar (char c)
#define GETCHAR_PROTOTYPE char getchar (void)
#else /* _IAR_ */
#define PUTCHAR_PROTOTYPE int putchar (int c)
#define GETCHAR_PROTOTYPE int getchar (void)
#endif /* _RAISONANCE_ */

void Uart1_Init(void);
void UART1_SendByte(u8 data);
void UART1_SendStr(u8 *str);

#ifdef _IAR_
int fputc(int ch, FILE *f);
#endif

#endif

stm8l15x_it.c中:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM