初識STM8S105K心得!


    最近由於公司項目需要STM8S105K這顆芯片,這兩天我也搗鼓了下,正好現在開通了博客,以此記錄下自己的工作。

    開發環境:

        window10操作系統;

        IAR for STM8;

    開發工具;

        window10電腦;

        STM8S105K4t6最小系統;

        ST-link燒錄器

   本人之前工作上主要使用STM32芯片,開發STM8S時,是使用ST的庫開發還是直接操作寄存器開發的選擇上,考慮到STM32上主要使用的庫,而STM8S是八位單片機,寄存器相對於STM32簡單不少,故本人使用寄存器操作開發。我以講解程序案列來與大家分享心得。

 實驗案例使用到的資源:

  1,IO口的位操作

  2,串口發送以及串口接收與空閑中斷

  3,定時器1的使用

    首先,使用IAR新建一個基礎工程

    對於STM8S的IO口操作,我們可以向使用51單片機那樣簡單直接位操作,我通過宏定義來對於位操作:

#define LED0_Toggle PE_ODR_bit.ODR5 = !PE_ODR_bit.ODR5 //LED接在PE5上
#define LED1_Toggle PC_ODR_bit.ODR1 = !PC_ODR_bit.ODR1 //LED接在PC1上
#define LED0 PE_ODR_bit.ODR5
#define LED1 PC_ODR_bit.ODR1

    上面代碼中對於了兩個LED燈,然后配置下IO口就可以實現燈的亮滅,IO配置如下:

 void GPIO_init(void)
{
PE_DDR = (1<<5); // 配置PE端口的方向寄存器PD3輸出
PE_CR1 = (1<<5); // 設置PE5為推挽輸出

PC_DDR = (1<<1); // 配置PC端口的方向寄存器PD3輸出
PC_CR1 = (1<<1); // 設置PC1為推挽輸出
}

    STM8S的串口使用前,我們實現要清楚STM8S的系統時鍾,我使用的時STM8S的內部16M時鍾作為時鍾源,然后1分頻作為系統時鍾,時鍾設置代碼如下:

/*******************************************************************************
* 函數名 : CLK_init
* 描述 : 內部16M時鍾作為系統時鍾
* 輸入 :
* 輸出 :
* 返回 :
* 注意 :
*******************************************************************************/
void CLK_init(void)
{

CLK_CKDIVR = 0x00; // 16M內部RC經1分頻后系統時鍾為16M

}

    我們知道系統設置后對串口波特率就好計算了。串口設置:波特率115200,數據位8,停止位1,奇偶校驗None,串口初始化主要進行串口參數設置,使能發送與接收,以及開通接收中斷與空閑中斷,最后開啟總中斷。初始化函數如下:

/*******************************************************************************
* 函數名 : GPIO_init
* 描述 : GPIO初始化
* 輸入 :
* 輸出 :
* 返回 :
* 注意 :
*******************************************************************************/
void UART2_Init(void)
{
asm("sim"); // 關全局中斷
/*寄存器恢復到默認值*/
UART2_CR3 = 0x00;
UART2_CR2 = 0x00;
UART2_CR3 = 0x00;

UART2_CR2 = 0x3c; //使能發送和接收,及使能接收中斷和空閑中斷

UART2_BRR2 = 0x0b;//波特率115200
UART2_BRR1 = 0x08;
asm("rim"); // 關全局中斷
}

    STM8S串口接收數據,我使用接收中斷和空閑中斷來完成數據的接收。當發送字符串時,每收到一個字符時觸發接收中斷,而只有當數據接收完檢測到空閑時才觸發空閑中斷,中斷代碼如下:

#pragma vector=UART2_R_RXNE_vector
__interrupt void UART2_RX_IRQHandler(void)
{
static unsigned char i=0;
static unsigned char RXBuff[20];


if(UART2_SR&0x20)
{

RXBuff[i++]=UART2_DR;//對UART_DR的讀操作可以將該位清零
;
}
if(UART2_SR&0x10)
{

printf("%s \n",RXBuff);
i=UART2_SR; //對UART_DR的讀操作可以將該位清零
i=UART2_DR;
i=0;

}

}

    而串口發送數據使用printfd的話就很方便,我也添加實現printf的代碼,代碼如下:

/*******************************************************************************
* 函數名:UART2_SendByte
* 描述 :uart發送一個字符
* 輸入 :u8 Dat 發送的字符
* 輸出 :無
* 返回 :
* 注意 :
*******************************************************************************/
void UART2_SendByte(unsigned char dat)
{
UART2_DR = dat;
while(!(UART2_SR&0x40)); //發送標志位是否為空
}

/*******************************************************************************
* 函數名:UART2_SendString
* 描述 :uart發送字符串
* 輸入 :u8* Data,u16 len
* 輸出 :無
* 返回 :
* 注意 :
*******************************************************************************/
void UART2_SendString(unsigned char* Data,unsigned short len)
{
unsigned short i=0;
for(;i<len;i++)
UART2_SendByte(Data[i]);

}

/*******************************************************************************
* 函數名:fputc
* 描述 :重定向c庫函數printf到USART1
* 輸入 :無
* 輸出 :無
* 返回 :
* 注意 : 由printf調用
*******************************************************************************/
int fputc(int ch, FILE *f)
{
/*將Printf內容發往串口*/
UART2_SendByte(ch);
return (ch);
}

     關於定時器的使用,比較簡單,主要實現LED燈的亮滅,我就不多講,附上代碼,代碼上有很多注釋,代碼如下

/*******************************************************************************
* 函數名 : TIM1_init
* 描述 : 定時器1初始化
* 輸入 :
* 輸出 :
* 返回 :
* 注意 : 中斷周期500ms
*******************************************************************************/
void TIM1_init(void)
{
asm("sim"); // 關全局中斷
TIM1_PSCRH = 0x3F; // 8M系統時鍾經預分頻f=fck/(PSCR+1)
TIM1_PSCRL = 0x7F; // PSCR=0x1F3F,f=16M/(0x3F7F+1)=1000Hz,每個計數周期1ms
TIM1_ARRH = 0x01; // 自動重載寄存器ARR=0x01F4=500
TIM1_ARRL = 0xF4; // 每記數500次產生一次中斷,即500ms
TIM1_IER = 0x01; // 允許更新中斷
TIM1_CR1 = 0x01; // 計數器使能,開始計數
asm("rim"); // 開全局中斷
}



/*******************************************************************************
* 函數名 : TIM1_OVR_UIF
* 描述 : 定時器1中斷函數,處理中斷事物
* 輸入 :
* 輸出 :
* 返回 :
* 注意 : 一點要清除中斷標志
*******************************************************************************/
#pragma vector=TIM1_OVR_UIF_vector
__interrupt void TIM1_OVR_UIF(void)
{
if(TIM1_SR1&0x01)
{
LED0=!LED0;
LED1=!LED1;
TIM1_SR1= 0x00; // 清除更新中斷標記,這步不能漏掉,否則會連續進入中斷程序
}

}

    最后我把工程代碼上傳,以供大家下載,如有不妥,歡迎大家留言。

TEST_Pro.rar


免責聲明!

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



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