stm32調試記 |
回復數(shù):52,點擊數(shù):5934 |
【樓主位】 sanhope 積分:42 派別: 等級:------ 來自:
|
第一節(jié): 陌生的她和大叔 人近中年,不知不覺竟然成為孩子的父親,不知不覺竟然成為別人的大叔,心中很是彷徨,我已不再年少。前些日子學習stm8,一口氣工作近2個星期,當時精神飽滿,心中很是得意,原來我也可以年輕。誰知放假去了次青島和家人度假回來后竟然感冒了一個星期,哎,我還是老了。 寫完stm8調試記后,就想踐踏一下stm32,就像大叔和美女。。。因為只有美女才能讓大叔覺得年輕,只有美女才能讓大叔精力旺盛,stm32是我的美女嗎?我不知道,我要接近她,我要駕馭她。 KEIL 的大名人盡皆知,51年代就大放異彩。說到這兒,不得不說一下那些為電子公益事業(yè)做出貢獻的先行者們。甚是懷念那個年代,丁丁,老萬,所長,午夜聽風,龍嘯九天等諸多大蝦。他們推廣keil,他們無私的奉獻,就像現(xiàn)在的老key一樣,知無不言,言無不盡。 我使用的環(huán)境: keil mdk 350 St 的 三合一板 板子雖小,還是可以做很多事情的,白菜老弟做的板子據(jù)說很強勢,已經預定,現(xiàn)在先解下渴,玩玩只有一個STM32F103C8T6的小家碧玉。 Mdk350集成了st的st link,所以只要在OPTION FOR TARGET 的 DEBUG 和UTILITIES下選擇st link debug就可以正確連接。庫使用的是v2.01
我要讓她跑起來,我需要做什么?
我要有一個時鐘,目標是48mhz,這是為了以后調試usb
STM32的時鐘和STM8的時鐘基本上是一樣的。她內部有個8mhz的振蕩器,不過我不打算用它。三合一板外部焊接了一個8mhz的晶振我要用她做時鐘源。 時鐘初始化:
RCC_DeInit(); //恢復默認值這沒什么用,不寫他也不影響運行
RCC_HSEConfig(RCC_HSE_ON ); //啟動外部時鐘
while(!RCC_GetFlagStatus(RCC_FLAG_HSERDY));//等待外部時鐘穩(wěn)定
FLASH_SetLatency(FLASH_Latency_1); //48mhz運行時,flash要加一個等待周期 其實剛開始時我沒有加這個延時,也沒有什么不良的反應,不知道時間長了會不會有問題
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//預緩沖使能
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_6);//pll輸出是外部時鐘的6倍
RCC_PLLCmd(ENABLE); //使能pll
while(!RCC_GetFlagStatus(RCC_FLAG_PLLRDY));//等待pll穩(wěn)定
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);//切換到PLL時鐘
while(RCC_GetSYSCLKSource()!=0x8);//等待系統(tǒng)時鐘穩(wěn)定 RCC_PCLK1Config(RCC_HCLK_Div2);//低速時鐘為24mhz
RCC_PCLK2Config(RCC_HCLK_Div1);//高速時鐘為48mhz
經過上面的設置,時鐘正是工作,我們可以通過這個函數(shù)RCC_GetClocksFreq(); 來驗證 RCC_ClocksTypeDef RCC_Clocks_T; RCC_GetClocksFreq( &RCC_Clocks_T); RCC_Clocks_T中反應了sys clk, HCLK PCLK1,PCLK2, ADC CLK的頻率。
時鐘有了,我們還要干點什么?板上有她唯一的外設,led小燈。我要讓處于pb5的led亮。 //首先開啟PB口的時鐘,pb口在高速apb2上 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE ); 下面要進行pb口的初始化
GPIO_InitTypeDef GPIOB_STR; //定義一個結構變量用于初始化 GPIOB_STR.GPIO_Pin = GPIO_Pin_5; //選擇pb5
GPIOB_STR.GPIO_Speed = GPIO_Speed_10MHz; //最大10mhz輸出
GPIOB_STR.GPIO_Mode = GPIO_Mode_Out_PP;//推挽輸出
GPIO_Init( GPIOB,&GPIOB_STR); //配置pb5 Pb5已經配置好了,下面我要點亮led,pb5要輸出1 GPIO_SetBits( GPIOB,GPIO_Pin_5); 相反熄滅她如下: GPIO_ResetBits( GPIOB,GPIO_Pin_5); 這一節(jié)就到這,意法的庫真是好東西,stm8調試的時候沒有使用是因為實在不愿看那么多的代碼?,F(xiàn)在學習stm32,順便把她的庫看了看,覺得雖然龐大瑣碎,但結構很優(yōu)美,便用了起來。不過我怕用習慣了,把我自己用傻了,以后換別的cpu時,不會用了。
第二節(jié) 定時,中斷,和意法的風騷 玩cpu嗎當然等玩定時器,重要性在stm8一文中已有描述,這里不再多說。 我要使用tim2實現(xiàn)1s定時,這有些長不夠實用,但是我只是玩玩。 第一步要配置時鐘 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_SPI2,ENABLE);
Tim2處于時鐘樹的apb1上。 下面是初始化代碼 TIM2->PSC |=24000; //設置預分頻,實現(xiàn)1ms
TIM2->ARR = 1000; //1s產生一次中斷
TIM2->DIER |=0X1; //允許tim2更新中斷
NVIC->ISER[0] |= (u32)(1<<TIM2_IRQChannel); //開tim2中斷
TIM2->CR1 |=0X1;//啟動tim2 說到這,不能不說意法的風騷,剛開始時翻遍手冊也沒看到nvic部分的說明,所以第一版本的tim2初始化沒有nvic部分,以至不能進tim2的更新中斷,后查閱阿莫的論壇才知有c_m3權威指南一物,實在讓人無語。這是意法的風騷,這是新手的災難。 每次新建工程時,keil會自動生成一個文件stm32f10x.s,在里面有中斷向量表的描述。將相應的中斷函數(shù)名實例化,就能實現(xiàn)中斷入口。 我的tim2中斷函數(shù) void TIM2_IRQHandler(void)//這個函數(shù)名能在stm32f10x.s中找到 { static u8 flag; if( flag ) { GPIO_SetBits( GPIOB,GPIO_Pin_5); //下面能實現(xiàn)上文說的led以0.5hz閃爍
flag = FALSE;
} else { GPIO_ResetBits( GPIOB,GPIO_Pin_5);
flag = TRUE; }
TIM2->SR &=0XFFFE; //清楚更新標志
}
上面沒有用庫函數(shù),是因為我想自己的頭腦里脈絡更清楚,更復合我自己的風格。其實用庫會簡單
第三節(jié) SPI和懶懶的我 調試stm8時沒有調spi實在是因為沒有接口,在加上我這人懶散最終沒有調它,如果是美女,我就不會這么客氣了吧。 最近身體欠佳,總感覺力不從心。又覺得時間匆匆,再不加把力氣真要荒廢此生,便生出無奈。 閑話少說,說說spi吧。三合一板只有一個cpu,但它卻有兩個spi,我用飛線將他們互聯(lián),便形成了一個完整的spi通訊接口。 Spi2處于時鐘樹的apb1,spi1處于時鐘樹的apb2,時鐘部分已將apb1配置為24mhz Apb2為48mhz 首先開啟spi2和spi1時鐘 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2\ |RCC_APB1Periph_SPI2, \\這個是spi2的選項 ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB\ |RCC_APB2Periph_SPI1\ //這個是spi1的選項 |RCC_APB2Periph_GPIOA\ |RCC_APB2Periph_USART1,ENABLE
); 下面是spi的初始化 u32 x; u8 y;
SPI_InitTypeDef SPI_X;
SPI_X.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //全雙工
SPI_X.SPI_Mode = SPI_Mode_Slave;//式
SPI_X.SPI_DataSize = SPI_DataSize_8b;//
SPI_X.SPI_CPOL = SPI_CPOL_High;//時鐘空閑是為高
SPI_X.SPI_CPHA = SPI_CPHA_2Edge;//
SPI_X.SPI_NSS = SPI_NSS_Soft;//軟件控制
SPI_X.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_X.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI2,&SPI_X);
SPI2->CR2 |= (1<<SPI_FLAG_RXENIE)|(1<<SPI_FLAG_TXENIE);//接受和發(fā)送 中斷
NVIC->ISER[1] |= 0X10;//開spi2中斷
SPI_X.SPI_Mode = SPI_Mode_Master;
SPI_Init(SPI1,&SPI_X); //spi1為主
SPI1->CR2 |= (1<<SPI_FLAG_RXENIE)|(1<<SPI_FLAG_TXENIE);
NVIC->ISER[1] |= 0X8;
SPI_Cmd(SPI2,ENABLE);
SPI_Cmd(SPI1,ENABLE);//使能spi1和spi2
SPI2->DR = 0Xaa;//發(fā)送數(shù)據(jù)
中斷處理函數(shù) void SPI1_IRQHandler( void ) { u16 x; if( SPI1->SR &0X1) { x = SPI1->DR;
}
if( SPI1->SR&0x2 ) { SPI1->DR =++test_data1;
}
}
void SPI2_IRQHandler( void ) { vu16 x; if( SPI2->SR &0X1) { x = SPI2->DR;
if( sam_data < SIZE_BUF ) {
sam_data1[ sam_data++ ] =x;
} else { sam_data = 0; } }
if( SPI2->SR&0x2 ) { SPI2->DR =++test_data; /* if(test_data1!=0) { test_data1 --; } else { test_data1 =10; } */ }
}
外設使用的時候一定要先配置好io的使用模式。我就因為沒有配置而吃了大虧。剛開始時收發(fā)怎么也不正常,后設置了io的方式才能工作。這大概是對新的事物還不熟悉。 Io的模式無非是,出的數(shù)據(jù)流設成輸出,入的數(shù)據(jù)流設成輸入,什么可說。
關于spi的代碼,不是好的風格,其中庫夾雜著自己的方法,如果在嚴格的風格上這不叫方法,叫發(fā)瘋。 第四節(jié):串口和新鳳霞 最近聽新鳳霞的花為媒,讓我有繞梁三日的感覺。喜歡的朋友可以聽一下。老藝術家的東西越來越少了。時代在進步,我們在放棄。但放棄的都是優(yōu)良的傳統(tǒng),如清廉,孝道,公正。 我手里有兩個自己做的ch341轉串口線纜,將小板的pa9(u1_TX,設置成推挽輸出),和pa10(U1_RX,上拉輸入) 和ch341相連,就完成了硬件配置。 我要實現(xiàn)的功能,當cpu收到計算機發(fā)來的0XAA時,發(fā)送8個0X55,在上電時cpu主動發(fā)送一次8個0X55.
首先配置時鐘, RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB\ |RCC_APB2Periph_SPI1\ //這個是spi1的選項 |RCC_APB2Periph_GPIOA\ |RCC_APB2Periph_USART1,ENABLE //這個是串口項
); 下面是初始化: USART_InitTypeDef uart_x;
NVIC_InitTypeDef nvic_x;
USART_Cmd(USART1,ENABLE); //使能串口
uart_x.USART_BaudRate = 19200;//19200, 8, n ,1
uart_x.USART_WordLength = USART_WordLength_8b;
uart_x.USART_StopBits = USART_StopBits_1;
uart_x.USART_Parity = USART_Parity_No;
uart_x.USART_Mode = USART_Mode_Rx |USART_Mode_Tx;//發(fā)送和接受
uart_x.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1,&uart_x);
USART_ITConfig(USART1,USART_IT_TC,ENABLE);//使能發(fā)送完成中斷
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能接受滿中斷
nvic_x.NVIC_IRQChannel = USART1_IRQChannel;//nvic的庫開啟方法
nvic_x.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_x);
中斷函數(shù) void USART1_IRQHandler( void ) { vu16 x; vu16 y ;
y = USART1->SR;//讀狀態(tài) if(y & 0X20)//如果是非空中斷 { x = USART1->DR&(u16)0xff; // USART_SendData(USART1,0X55);
if( x == 0xaa ) { lentch_x = 0;
USART1->CR1 |=(u16)0X8;//啟動一次發(fā)送
}
} if(y & 0X40)//發(fā)送完成中斷 {
if(lentch_x < 8 ) {
USART1->DR = 0X55;
lentch_x++;
} else { USART1->CR1 &=(u16)0XFFF7;; //清楚標志
}
}
}
這次完全使用了庫,哈。過兩天使用dma試試,接下來還有adc等沒有測試,可板子太小了可發(fā)揮的余地不多,就剩usb了,可是它太不好肯,得好好的準備準備,過陣子白菜的板子到了在研究。
|
|
2009-06-11,11:24:57 |
|
【1樓】 sunsky 積分:176 派別: 等級:------ 來自:
|
非常精彩。 |
|
2009-06-11,12:23:11 |
|
【2樓】 lollipop 天堂里沒有豬頭豬腦
 積分:604 派別: 等級:------ 來自:上海
|
有意思 |
|
2009-06-11,12:57:30 |
|
【3樓】 kakaarm 積分:144 派別: 等級:------ 來自:ARM新品:路虎LPC1768開發(fā)板(Cortex-M3),板載USB仿真器!JLINK On Board
|
大叔大有文采啦,你不搞文學那是文學界的一大損失啊呵呵 |
|
2009-06-11,15:14:52 |
|
【4樓】 zx5111030 積分:178 派別: 等級:------ 來自:北京
|
mark |
|
2009-06-11,16:47:51 |
|
【5樓】 lihq97 積分:47 派別: 等級:------ 來自:廣東江門市新會區(qū)
|
很精彩,對我們新手很有幫助! |
|
2009-06-14,09:17:54 |
|
【6樓】 qfmcu 清風徐徐
 積分:216 派別: 等級:------ 來自:濟南
|
非常精彩,有續(xù)集否? |
|