必須準備一個基本的系統來調控各種功能。
絕大部分的控制,都跟時間有關,
所以接下來要講的是一個根據時間運作來操作的系統。
並且要把UART的連線做起來,
使得PC或者另一端能夠藉此下指令或是讀取晶片內部資料之類的。
基本的硬體如圖連接。
如上圖所示,為了方便所以將 STM8發展板放在麵包板上。
接線也只是使用 UART的端口接往 CP2102。
CP2102 是一顆UART轉 USB的晶片,安裝後在PC端機將會出現個RS-232介面。
我們使用 Terminal 這個軟體讀取資訊。
按照之前的教學建立一個新的STM8專案。
寫出的程式碼如下:
main.c
#include <stdint.h>
#include <stdio.h>
#include "STM8S.h"
#include "misc.h"
struct BitFlag SysFlag;
unsigned char time10ms,RXTimer;
unsigned char RXIndex;
unsigned char RXBuf[20];
void UART2Recive(void) __interrupt 21
{
RXBuf[RXIndex++] = UART2->DR;
RXTimer=0;
__asm__("bres 0x5240,#5\n"); //clear UART2->SR->RXNE
}
void Tim4Int(void) __interrupt 23
{
TIM4->SR1=0;
time10ms++;
if(RXIndex>0){RXTimer++;}
}
void main(void)
{
SystemInit();
UartInit();
SysFlag.RXDone = 0;
RXIndex=0;
time10ms=0;
RXTimer=0;
GPIOE->ODR&=~(0x20);
enableInterrupts();
while(1)
{
if(time10ms>50)
{
__asm__("bcpl 0x5014,#5\n");//GPIOE->ODR = GPIOE->ODR ^ 0x20;
time10ms=time10ms-50;
}
if(RXTimer>10)
{
unsigned char i;
printf("%d",RXIndex);
for(i=0;i<RXIndex;i++)
{
putchar(RXBuf[i]);
}
RXIndex=0;
RXTimer=0;
SysFlag.RXDone=1;
}
if(SysFlag.RXDone)
{
SysFlag.RXDone=0;
}
}
}
在main.c之中,建立了兩個中斷,分別是UART與Timer4。
晶片的震盪頻率是 2MHz,而 Timer 4 根據取得的系統頻率去除頻
產生每次中斷時間為 10.04mS。
這段程式被寫在副程式 SystemInit() 並且放在misc.c內。
UartInit()副程式啟動了 UART,同樣放在misc.c內。
time10ms 則是被作用於時間的計數值,每經過10ms就會被加一。
在下面的永久回圈內,可以利用每計時到 500ms 也就是 0.5 秒的時候,
將LED的腳位信號反轉。
RXTimer則是UART接收的計數值,在UART接收資料停止後開始計時,
計時滿100ms時代表已經接收完畢,進行接收資料後的處理。
之後對於接收指令後的解碼與相對應的處理程式可以放在這。
此處的範例是接收後回傳收到的字元數以及字元內容。
SysFlag 是一組旗標組合成的資料區,目前暫時沒有使用。
misc.c
#include "stm8s.h"
#include "misc.h"
extern struct BitFlag SysFlag;
void SystemInit(void)
{
CLK->CKDIVR = CLK_CKDIVR_RESET_VALUE; // Set the frequency to 2 MHz
GPIOE->DDR = 0x20;
GPIOE->CR1 = 0x20;
/*
Configure timer
fmaster = 2 MHz,
Tim4 clk time = 1/(2M/(2^7)) =1/15.625KHz=64uS
one interrupt time is 64us * 157 = 10.048mS
*/
TIM4->CR1 = TIM4_CR1_CEN;
TIM4->PSCR = 0x07;
TIM4->EGR = 0x01;
TIM4->ARR = 157;
TIM4->IER = 0x01;
}
void UartInit(void)
{
/*
UART2 Baud rate =9600,
BR register = 2M / 9600 = 208.3 = 0xD1
*/
UART2->SR &=0xBF;
UART2->BRR1 =0x0D;UART2->BRR2=0x01;
UART2->CR1 = 0x00;
UART2->CR2 = UART2_CR2_RIEN | UART2_CR2_TEN|UART2_CR2_REN;
UART2->CR3 = 0x00;
}
void putchar(char c)
{
while(((UART2->SR)&0x80) != 0x80);
UART2->DR=c;
}
在misc.c內除了基本的系統初始化與UART初始化之外,
還放了一個副程式 putchar。
這個副程式的目的是要讓sdcc的printf函式能夠被使用。
當然使用這個副程式後整個程式碼大爆增了 2Kbyte,
通常會在整個製作完成後移除printf這個功能,儘量使用puts就好。
misc.h
#ifndef _MISC_H
#define _MISC_H
void SystemInit(void);
void UartInit(void);
void putchar(char);
struct BitFlag{
unsigned x1 :1; // UART received OK
unsigned RXDone :1;
unsigned x2 :1; // Go to boot loader
unsigned x3 :1; //
unsigned x4 :1;
unsigned x5 :1;
unsigned x6 :1;
unsigned x7 :1;
};
#endif // misc_H
最後是 misc.h 。這裡利用 struct 建立一個 bit field。
準備做系統旗標使用。
不過sdcc在轉譯這方面的程式,並不像mspgcc那樣會轉譯為針對單一位元運作的指令。
轉譯結果,相當占code空間 |
完成這些程式並且燒錄後,可以運用PC端來跟晶片通訊:
並且LED燈呈現每0.5秒就變化一次,方便確認是否出現當機。
所有程式碼均已放上GitHub
前輩 可以跟您請教一下 目前您還有在使用 STM8S 系列的MCU做開發嗎?
回覆刪除目前有建議什麼 IDE與toolchain嗎?
感謝您的無私分享~
可以用IAR 或者 COSMIC 這兩套軟體來開發, IAR 須用付費軟體,COSMIC 免費https://www.cosmic-software.com/download.php
刪除