魚和熊掌兼得---STM32調(diào)試接口SW動態(tài)復(fù)用為GPIO的方法
STM32單片機的調(diào)試接口一般有JTAG和SW兩種,JTAG接口因為需要的管腳較多,故此僅在一些學(xué)習(xí)用的開發(fā)板上能夠見到,批量化生產(chǎn)的產(chǎn)品中極少用到。而SW接口僅需要兩個管腳(PA13和PA14),是使用較為普遍的調(diào)試接口。做為調(diào)試專用管腳,一旦在程序中將其設(shè)置為了普通GPIO,若想再通過SW調(diào)試則必須通過ISP方式下載新的程序(沒有進行GPIO設(shè)置的程序),給調(diào)試帶來很多不便。下面討論如何做到PA13和PA14如果即能保證正常調(diào)試功能又可當(dāng)GPIO的方法。
(1)做為輸入管腳
當(dāng)使用調(diào)試接口做為輸出時,不需要進行什么特殊設(shè)置,在任何時候直接使用讀取語句讀取即可,不會影響到SW調(diào)試功能。
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13);//讀取PA13(SW_DAT)電平
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14);//讀取PA14(SW_CLK)電平
(2)做為輸出管腳
在程序開始時判斷當(dāng)前是否連接了SW調(diào)試器,若未連接時才去設(shè)置PA13和PA14為輸出GPIO。
重點是如何判斷是否連接了調(diào)試器,我對STM32的函數(shù)庫并不是特別熟悉,經(jīng)過簡單不負責(zé)任的尋找后并沒有發(fā)現(xiàn)有這方面的現(xiàn)成函數(shù),所以就土法上馬了。
我們知道,如果連接了調(diào)試器時,不管是CLK還是DAT管腳,都會有無數(shù)的方波(調(diào)試嘛,一定是有方波的,要不然怎么進行數(shù)據(jù)交互),既然任何時候都可以用讀取指令獲取管腳的電平狀態(tài),那么只要判斷一下是不是有電平變化就可以了(方波),下面是個粗暴的判斷函數(shù)。
unsigned char PA14IsDBG=0;
unsigned char CheckPA14IsDBG(void)
{
unsigned short i,j,s;
if (PA14IsDBG==1) return 1;// PA14IsDBG是全局變量
for (i=0;i<100;i++)
{
s=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_14);
for (j=0;j<1000;j++)
{
if (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_14)!=s)
{
PA14IsDBG=1;
UART1_SendString("Is Debug\r\n");
return 1;
}
//__NOP();
}
}
return 0;
}
上面的函數(shù)是使用PA14(SW_CLK)管腳進行檢測,若使用PA13(SW_DAT)也同樣是可以的。
設(shè)置PA14(SW_CLK)為輸出
void SetPA14IsOut(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
If (PA14IsDBG) return;
GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable,ENABLE);//*禁用調(diào)試接口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA||RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//一定要是開漏輸出
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void SetPA14IsDbg(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//使能SW調(diào)試接口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA||RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//設(shè)置PA14輸出高低電平
void PA14OutH(void)
{
if (PA14IsDBG) return;
GPIO_SetBits(GPIOA, GPIO_Pin_14);
}
void PA14OutL(void)
{
if (PA14IsDBG) return;
GPIO_ResetBits(GPIOA, GPIO_Pin_14);
}
void main(void)
{
CheckPA14IsDBG();
SetPA14IsOut();
while (1)
{
PA14OutH();
Delay_ms(500);
PA14OutL();
Delay_ms(500);
CheckPA14IsDBGLK();
if (PA14IsDBG) SetPA14IsDbg();
}
}
需要注意的幾點:
(1)上電后,必須遲早調(diào)用CheckPA14IsDBG();
(2)在整個程序中,僅可調(diào)用一次SetPA14IsOut();且必須在CheckPA14IsDBG();之后。
(3)PA13或者PA14做為輸出時,只能配置為開漏輸出,這一點非常重要(其實修改一下代碼也可以強推挽,明白其中原理就沒有問題)。
(4)在程序運行過程中,要經(jīng)常調(diào)用CheckPA14IsDBG();來檢測是否有調(diào)試信號出現(xiàn),以便恢復(fù)為SW功能。
(5)若單片機曾經(jīng)在非調(diào)試狀態(tài)運行過,則再次調(diào)試時可能失敗,多試幾次就好了。
(6)以上代碼使用了PA14,同樣適用于PA13,將代碼中的PA14改為PA13即可。
相關(guān)產(chǎn)品
免責(zé)聲明
- 凡本網(wǎng)注明“來源:化工儀器網(wǎng)”的所有作品,均為浙江興旺寶明通網(wǎng)絡(luò)有限公司-化工儀器網(wǎng)合法擁有版權(quán)或有權(quán)使用的作品,未經(jīng)本網(wǎng)授權(quán)不得轉(zhuǎn)載、摘編或利用其它方式使用上述作品。已經(jīng)本網(wǎng)授權(quán)使用作品的,應(yīng)在授權(quán)范圍內(nèi)使用,并注明“來源:化工儀器網(wǎng)”。違反上述聲明者,本網(wǎng)將追究其相關(guān)法律責(zé)任。
- 本網(wǎng)轉(zhuǎn)載并注明自其他來源(非化工儀器網(wǎng))的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點和對其真實性負責(zé),不承擔(dān)此類作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個人從本網(wǎng)轉(zhuǎn)載時,必須保留本網(wǎng)注明的作品第一來源,并自負版權(quán)等法律責(zé)任。
- 如涉及作品內(nèi)容、版權(quán)等問題,請在作品發(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。