魚(yú)和熊掌兼得---STM32調(diào)試接口SW動(dòng)態(tài)復(fù)用為GPIO的方法
STM32單片機(jī)的調(diào)試接口一般有JTAG和SW兩種,JTAG接口因?yàn)樾枰墓苣_較多,故此僅在一些學(xué)習(xí)用的開(kāi)發(fā)板上能夠見(jiàn)到,批量化生產(chǎn)的產(chǎn)品中極少用到。而SW接口僅需要兩個(gè)管腳(PA13和PA14),是使用較為普遍的調(diào)試接口。做為調(diào)試專(zhuān)用管腳,一旦在程序中將其設(shè)置為了普通GPIO,若想再通過(guò)SW調(diào)試則必須通過(guò)ISP方式下載新的程序(沒(méi)有進(jìn)行GPIO設(shè)置的程序),給調(diào)試帶來(lái)很多不便。下面討論如何做到PA13和PA14如果即能保證正常調(diào)試功能又可當(dāng)GPIO的方法。
(1)做為輸入管腳
當(dāng)使用調(diào)試接口做為輸出時(shí),不需要進(jìn)行什么特殊設(shè)置,在任何時(shí)候直接使用讀取語(yǔ)句讀取即可,不會(huì)影響到SW調(diào)試功能。
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13);//讀取PA13(SW_DAT)電平
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14);//讀取PA14(SW_CLK)電平
(2)做為輸出管腳
在程序開(kāi)始時(shí)判斷當(dāng)前是否連接了SW調(diào)試器,若未連接時(shí)才去設(shè)置PA13和PA14為輸出GPIO。
重點(diǎn)是如何判斷是否連接了調(diào)試器,我對(duì)STM32的函數(shù)庫(kù)并不是特別熟悉,經(jīng)過(guò)簡(jiǎn)單不負(fù)責(zé)任的尋找后并沒(méi)有發(fā)現(xiàn)有這方面的現(xiàn)成函數(shù),所以就土法上馬了。
我們知道,如果連接了調(diào)試器時(shí),不管是CLK還是DAT管腳,都會(huì)有無(wú)數(shù)的方波(調(diào)試嘛,一定是有方波的,要不然怎么進(jìn)行數(shù)據(jù)交互),既然任何時(shí)候都可以用讀取指令獲取管腳的電平狀態(tài),那么只要判斷一下是不是有電平變化就可以了(方波),下面是個(gè)粗暴的判斷函數(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)管腳進(jìn)行檢測(cè),若使用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;//一定要是開(kāi)漏輸出
//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();
}
}
需要注意的幾點(diǎn):
(1)上電后,必須遲早調(diào)用CheckPA14IsDBG();
(2)在整個(gè)程序中,僅可調(diào)用一次SetPA14IsOut();且必須在CheckPA14IsDBG();之后。
(3)PA13或者PA14做為輸出時(shí),只能配置為開(kāi)漏輸出,這一點(diǎn)非常重要(其實(shí)修改一下代碼也可以強(qiáng)推挽,明白其中原理就沒(méi)有問(wèn)題)。
(4)在程序運(yùn)行過(guò)程中,要經(jīng)常調(diào)用CheckPA14IsDBG();來(lái)檢測(cè)是否有調(diào)試信號(hào)出現(xiàn),以便恢復(fù)為SW功能。
(5)若單片機(jī)曾經(jīng)在非調(diào)試狀態(tài)運(yùn)行過(guò),則再次調(diào)試時(shí)可能失敗,多試幾次就好了。
(6)以上代碼使用了PA14,同樣適用于PA13,將代碼中的PA14改為PA13即可。
相關(guān)產(chǎn)品
免責(zé)聲明
- 凡本網(wǎng)注明“來(lái)源:化工儀器網(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)使用,并注明“來(lái)源:化工儀器網(wǎng)”。違反上述聲明者,本網(wǎng)將追究其相關(guān)法律責(zé)任。
- 本網(wǎng)轉(zhuǎn)載并注明自其他來(lái)源(非化工儀器網(wǎng))的作品,目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé),不承擔(dān)此類(lèi)作品侵權(quán)行為的直接責(zé)任及連帶責(zé)任。其他媒體、網(wǎng)站或個(gè)人從本網(wǎng)轉(zhuǎn)載時(shí),必須保留本網(wǎng)注明的作品第一來(lái)源,并自負(fù)版權(quán)等法律責(zé)任。
- 如涉及作品內(nèi)容、版權(quán)等問(wèn)題,請(qǐng)?jiān)谧髌钒l(fā)表之日起一周內(nèi)與本網(wǎng)聯(lián)系,否則視為放棄相關(guān)權(quán)利。