基于STM32平臺的ADC轉換加4路PWM波輸出并且使用12864顯示,基于德飛萊例程改寫,每一個功能都單獨寫的,方便了大家的移植,其中12864使用了PF口,ADC-PC1,PWM-PA6-7,PB0-1。
- #include "stm32f10x.h"
- #include "delay.h" //必須配合delay.c和delay.h文件使用,所以要包含delay.h。
- #include "display12864.h"
- #define u16 unsigned short //為了可移植性好,對這兩個 STM 32 已經定義過的變量,再定義一次。
- #define u8 unsigned char
- /********** 以下是相關引腳定義 **************/
- //此次所用IO為:GPIO-F 的 PF 0--7,8,9,10
- #define DisIO GPIOF //定義12864要使用的I/O端口。
- #define DisClk RCC_APB2Periph_GPIOF //定義12864要使用的I/O端口時鐘。RCC_APB2Periph_GPIOA
- #define Data GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7
- //定義12864使用的數據引腳。
- #define RS GPIO_Pin_8 //1高電平 data 選擇數據 低 無用
- #define RW GPIO_Pin_9 //高讀低寫
- #define EN GPIO_Pin_10 //使能信號 定義使能端使用的引腳。
- #define PSB GPIO_Pin_0 //定義并,串行數據模式的選擇端口使用的引腳。直接高電平,并口;低電平,串口。PC0
- /*********定義GPIO結構體 ********************/
-
- GPIO_InitTypeDef GPIOStru; //引腳號,速度,模式,定義用于定義所以引腳為輸出的變量。
- /****初始化 所有端口 為推挽輸出模式 *********/
- void IOInitOut(void) //把 所有端口 初始化為推挽輸出模式的函數。
- {
- GPIOStru.GPIO_Mode = GPIO_Mode_Out_PP; //引腳模式 定義所有的引腳為推挽輸出的變量初始化。
- GPIOStru.GPIO_Speed = GPIO_Speed_50MHz;
- GPIOStru.GPIO_Pin = PSB;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
- GPIO_Init(GPIOC,&GPIOStru); //對PC口初始化
-
- GPIOStru.GPIO_Mode = GPIO_Mode_Out_PP; //引腳模式 定義所有的引腳為推挽輸出的變量初始化。
- GPIOStru.GPIO_Speed = GPIO_Speed_50MHz; //時鐘頻率
- //GPIOStru.GPIO_Pin = Data|RS|RW|EN|PSB;
- GPIOStru.GPIO_Pin = Data|RS|RW|EN; //引腳號
- RCC_APB2PeriphClockCmd(DisClk,ENABLE); //使能 F引腳 的時鐘 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);
- GPIO_Init(DisIO,&GPIOStru); //引腳初始化 庫函數 GPIO_Init(GPIOF,&GPIOStru);
- }
- /****初始化數據data引腳為浮空輸入模式 *******/
- void IOInitIn(void) //把 數據引腳 初始化為浮空輸入的函數。
- {
- GPIOStru.GPIO_Mode = GPIO_Mode_IN_FLOATING; //定義數據引腳為浮空輸入的變量初始化。
- GPIOStru.GPIO_Speed = GPIO_Speed_50MHz;
- GPIOStru.GPIO_Pin = Data; //只定義數據引腳
- RCC_APB2PeriphClockCmd(DisClk,ENABLE); //把所有端口初始化為輸出模式的函數。
- GPIO_Init(DisIO,&GPIOStru);
- }
- /****等待12864的忙狀態結束 ******************/
- void WaitBusy(void) //等待12864的忙狀態結束的函數。
- {
- IOInitIn(); //把 數據引腳 定義為浮空輸入;
- GPIO_ResetBits(DisIO,RS); //RS = 0.
- GPIO_SetBits(DisIO,RW); //RW = 1.
- GPIO_SetBits(DisIO,EN); //EN = 1.
- while(GPIO_ReadInputData(DisIO) & 0x0080); //只要位7的值,位7是忙標志位。0--7 ,如果讀出為1高電平,則表示液晶屏處在忙狀態,當轉為0時
- GPIO_ResetBits(DisIO,EN); //EN = 0;
- IOInitOut(); //把所有引腳定義為輸出。
- }
- /*********寫命令函數 *********************/
- void WriteCmd(u8 cmd) //寫命令函數。
- {
- WaitBusy(); //等待12864忙狀態結束
- GPIO_ResetBits(DisIO,RS); //RS = 0.
- GPIO_ResetBits(DisIO,RW); //RW = 0.
- GPIO_SetBits(DisIO,EN); //EN = 1.
- DisIO->ODR=((DisIO->ODR & 0xff00)|cmd); //此處,只有直接操作寄存器才能
- //達到,只改變 輸出數據寄存器ODR 的低8位,其它位
- //不變的目的。因為,只有低8位是數據引腳,
- //其它位可能是控制引腳,不能改變。
- delay_ms(2);
- GPIO_ResetBits(DisIO,EN); //EN = 0;
- delay_ms(2);
- }
- /*********寫數據函數 *********************/
- void WriteData(u8 data) //寫數據函數。
- {
- WaitBusy();
- GPIO_SetBits(DisIO,RS); //RS = 1.
- GPIO_ResetBits(DisIO,RW); //RW = 0.
- GPIO_SetBits(DisIO,EN); //EN = 1.
- DisIO->ODR=((DisIO->ODR & 0xff00)|data); //同上。
- delay_ms(2);
- GPIO_ResetBits(DisIO,EN); //EN = 0;
- delay_ms(2);
- }
- /***初始化12864 和要用到的STM32 的GPIO******/
- void InitDis(void) //初始化 12864 和要用到的 STM 32 的引腳。
- {
- IOInitOut();
- //delay_init(8); //初始化延時函數的微妙計數基數。
- delay_init();
- GPIO_SetBits(GPIOC,PSB); //令PSB=1,設置為并行數據模式。
- delay_ms(2);
- WriteCmd(0x30); //選擇基本指令集,和,8位數據模式。
- delay_ms(2);
- WriteCmd(0x0c); //開顯示,無游標,不反白.
- delay_ms(2);
- WriteCmd(0x01); //清除顯示,并將 DDRAM 的地址計數器 AC 設為 00H.
- delay_ms(2);
- WriteCmd(0x06); //設置,外部讀寫數據后,地址記數器 AC 會自動加 1。
- delay_ms(2);
- WriteCmd(0x80); //將 DDRAM 地址計數器 AC 設為 0.
- delay_ms(2);
- }
- /*********顯示字符串的函數 ****************/
- void DisStr(u8 *s) //顯示字符串的函數。
- {
- while(*s != '\0')
- {
- WriteData(*s);
- s++;
- delay_ms(2); //控制每一個字符之間顯示的時間 間隔
- }
- }
- /*********顯示整型變量的函數 **************/
- void DisInt(long int num) //顯示整型變量的函數,最多顯示16位的整數。只能顯示正數。
- {
- u8 temp[17];
- u8 str[17];
- int i=0,j=0;
- while(num != 0) //這里不能用num%10 != 0,如果num是10的整數倍,
- //例如,100,這樣就會出錯,根本就不能進入循環體。
- {
- temp[i] = (num%10)+0x30;
- num/=10; //num 除以 10 = 剩下的樹的整數 124/10=12
- i++;
- }
- i--; //因為i在退出循環之前還自加了一次,此時,
- //指向最后一個存儲有用值的元素的后一個位置。
- while(i != -1) //因為i=0時,temp[0]還是有用值。
- {
- str[j] = temp[i];
- j++;
- i--;
- }
- str[j]='\0'; //因為i在退出循環之前還自加了一次,此時,
- //指向最后一個存儲有用值的元素的后一個位置。
- DisStr(str);
- }
- /********顯示有4位小數的浮點數 *************/
- void DisFloat(float fnum) //顯示有4位小數的浮點數,總位數不超過16位。
- {
- long int num = fnum*10000;
- u8 temp[17];
- u8 str[17];
- int i=0,j=0;
- while(num != 0)
- {
- temp[i] = (num%10)+0x30;
- num/=10;
- i++;
- if(i == 4) //4位小數處理完后,加入小數點。
- {
- temp[i] = '.';
- i++;
- }
- }
- i--;
- while(i != -1)
- {
- str[j] = temp[i];
- j++;
- i--;
- }
- str[j]='\0';
- DisStr(str);
- }
- /********清全屏函數 ***********************/
- void lcd_clear(void)
- {
- WriteCmd(0x01);
- }
- /********起始顯示位置設定函數 **************/
- void lcd_locate(u8 X,u8 Y)
- {
- switch(X)
- {
- case 1: WriteCmd(0x80+Y); break;
- case 2: WriteCmd(0x90+Y); break;
- case 3: WriteCmd(0x88+Y); break;
- case 4: WriteCmd(0x98+Y); break;
- }
- }
- /********位置顯示字符串函數 ****************/
- void lcd_DisStr(u8 X,u8 Y,u8 *s)
- {
- lcd_locate( X, Y);
- DisStr( s );
- }
復制代碼 ADC代碼:
- #include "adc.h"
- #include "stm32f10x.h "
- #define ADC1_DR_Address ((u32)0x40012400+0x4c)
- __IO uint16_t ADC_ConvertedValue;
- /*
- * 函數名:ADC1_GPIO_Config
- * 描述 :使能ADC1和DMA1的時鐘,初始化PC.01
- * 輸入 : 無
- * 輸出 :無
- * 調用 :內部調用
- */
- static void ADC1_GPIO_Config(void)
- {
- ADC_InitTypeDef ADC_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC |RCC_APB2Periph_ADC1 , ENABLE );
- RCC_ADCCLKConfig(RCC_PCLK2_Div6);
-
- /* Enable DMA clock */
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
-
- /* Enable ADC1 and GPIOC clock */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);
-
- /* Configure PC.01 as analog input */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
- GPIO_Init(GPIOC, &GPIO_InitStructure); // PC1,輸入時不用設置速率
- }
- /* 函數名:ADC1_Mode_Config
- * 描述 :配置ADC1的工作模式為MDA模式
- * 輸入 : 無
- * 輸出 :無
- * 調用 :內部調用
- */
- static void ADC1_Mode_Config(void)
- {
- DMA_InitTypeDef DMA_InitStructure;
- ADC_InitTypeDef ADC_InitStructure;
-
- /* DMA channel1 configuration */
- DMA_DeInit(DMA1_Channel1);
- DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC地址
- DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;//內存地址
- DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
- DMA_InitStructure.DMA_BufferSize = 1;
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外設地址固定
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //內存地址固定
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循環傳輸
- DMA_InitStructure.DMA_Priority = DMA_Priority_High;
- DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
- DMA_Init(DMA1_Channel1, &DMA_InitStructure);
-
- /* Enable DMA channel1 */
- DMA_Cmd(DMA1_Channel1, ENABLE);
-
- /* ADC1 configuration */
-
- ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //獨立ADC模式
- ADC_InitStructure.ADC_ScanConvMode = DISABLE ; //禁止掃描模式,掃描模式用于多通道采集
- ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //開啟連續轉換模式,即不停地進行ADC轉換
- ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部觸發轉換
- ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集數據右對齊
- ADC_InitStructure.ADC_NbrOfChannel = 1; //要轉換的通道數目1
- ADC_Init(ADC1, &ADC_InitStructure);
-
- /*配置ADC時鐘,為PCLK2的8分頻,即9Hz*/
- RCC_ADCCLKConfig(RCC_PCLK2_Div8);
- /*配置ADC1的通道11為55. 5個采樣周期,序列為1 */
- ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);
-
- /* Enable ADC1 DMA */
- ADC_DMACmd(ADC1, ENABLE);
-
- /* Enable ADC1 */
- ADC_Cmd(ADC1, ENABLE);
-
- /*復位校準寄存器 */
- ADC_ResetCalibration(ADC1);
- /*等待校準寄存器復位完成 */
- while(ADC_GetResetCalibrationStatus(ADC1));
-
- /* ADC校準 */
- ADC_StartCalibration(ADC1);
- /* 等待校準完成*/
- while(ADC_GetCalibrationStatus(ADC1));
-
- /* 由于沒有采用外部觸發,所以使用軟件觸發ADC轉換 */
- ADC_SoftwareStartConvCmd(ADC1, ENABLE);
- }
- /*
- * 函數名:ADC1_Init
- * 描述 :無
- * 輸入 :無
- * 輸出 :無
- * 調用 :外部調用
- */
- void ADC1_Init(void)
- {
- ADC1_GPIO_Config();
- ADC1_Mode_Config();
- }
復制代碼 PWM輸出代碼:
- #include "PWM_output.h"
- #define ARR 4000 //表示分頻后得到的頻率,為8MHZ除以ARR
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- TIM_OCInitTypeDef TIM_OCInitStructure;
- // uint16_t CCR1_Val = 4000; // (4000 / 8000) * 100% = 50%
- // uint16_t CCR2_Val = 3000; // (3000 / 8000) * 100% = 37.5%
- // uint16_t CCR3_Val = 2000; // (2000 / 8000) * 100% = 25%
- // uint16_t CCR4_Val = 1000; // (1000 / 8000) * 100% = 12.5%
- uint16_t CCR1_Val = ARR/2; // (4000 / 8000) * 100% = 50%
- uint16_t CCR2_Val = ARR/8*3; // (3000 / 8000) * 100% = 37.5%
- uint16_t CCR3_Val = ARR/4; // (2000 / 8000) * 100% = 25%
- uint16_t CCR4_Val = ARR/8; // (1000 / 8000) * 100% = 12.5%
- uint16_t PrescalerValue = 0;
- void RCC_Configuration(void);
- void GPIO_Configuration(void);
- /*******************************************************************************
- * 函數名 : RCC_Configuration
- * 描述 : RCC時鐘配置函數
- * 輸入 : 無
- * 輸出 : 無
- * 返回值 : 無
- * 注意 : 無
- *******************************************************************************/
- void RCC_Configuration(void)
- {
- /* TIM3 時鐘使能 */
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
- /* GPIOA 與 GPIOB 時鐘使能 */ //其為TIM3的4個通道
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
- // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
- }
- /*******************************************************************************
- * 函數名 : GPIO_Configuration
- * 描述 : 管腳配置
- * 輸入 : 無
- * 輸出 : 無
- * 返回值 : 無
- * 注意 : 無
- *******************************************************************************/
- void GPIO_Configuration(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出
- // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; //開漏輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- }
- /*******************************************************************************
- * 函數名 : PWM_Output_Init
- * 描述 : PWM輸出初始化函數
- * 輸入 : 無
- * 輸出 : 無
- * 返回值 : 無
- * 注意 : 無
- *******************************************************************************/
- void PWM_Output_Init(void)
- {
- /* 時鐘配置 */
- RCC_Configuration();
- /* 管腳配置 */
- GPIO_Configuration();
- /* -----------------------------------------------------------------------
- TIM3 配置: 輸出 4 通道的 PWM 信號:
- TIM3 預分頻系數計算:
- - Prescaler = (系統時鐘 / TIM3 計數時鐘) - 1
- 默認使能的系統時鐘為 72MHz
- TIM3 產生的頻率為 36KHz: TIM3 Frequency = TIM3 計數時鐘/(ARR + 1)
- = 8 MHz / 8000 = 1 KHz
- TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50%
- TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5%
- TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25%
- TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5%
- ----------------------------------------------------------------------- */
- /* 預分頻值計算 */
- PrescalerValue = (uint16_t) (SystemCoreClock / 8000000) - 1; //TIM3的預分頻系數 (72M / 8M) - 1 = 8 即為 9 分頻,即為8M的頻率
- /* 定時器配置 */
- //TIM_TimeBaseStructure.TIM_Period = (8000 - 1); //ARR值,定時器時鐘頻率 / (ARR + 1) -- 為PWM的輸出頻率值
- TIM_TimeBaseStructure.TIM_Period = (ARR-1);
- TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; //預分頻
- TIM_TimeBaseStructure.TIM_ClockDivision = 0;
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //計數方式為向上計數
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始TIM3
- /* 通道1配置 */
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM模式1
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //使能輸出
- TIM_OCInitStructure.TIM_Pulse = CCR1_Val; //(CCR1_Val / ARR值 ) * 100 為占空比值
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //輸出高
- TIM_OC1Init(TIM3, &TIM_OCInitStructure);
- TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); //重裝載使能
-
- /* 通道2配置 */
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
- TIM_OC2Init(TIM3, &TIM_OCInitStructure);
-
- TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
-
- /* 通道3配置 */
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
-
- TIM_OC3Init(TIM3, &TIM_OCInitStructure);
-
- TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
-
- /* 通道4配置 */
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
-
- TIM_OC4Init(TIM3, &TIM_OCInitStructure);
-
- TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
- TIM_ARRPreloadConfig(TIM3, ENABLE);
-
- /* TIM3 使能計數 */
- TIM_Cmd(TIM3, ENABLE);
- }
復制代碼
全部資料下載地址:
整體程序.zip
(1.97 MB, 下載次數: 91)
2017-8-3 10:22 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|