品牌
其他厂商性质
所在地
前言1
概述2
用途3
板上资源及其优势3
常规开发板与高频开发板的差异对比表6
准备工作6
例程简介6
实验1 流水灯6
实验2 中断检测按键9
实验3 12864液晶显示13
实验4 异步串行口(USART)的简单应用20
实验5 PWM输出.24
实验6ADC采集数据(采用DMA模式)28
实验7利用MF58测出环境温度并显示在12864液晶上32
负责声明
项目 | DYSTM32高频开发板 | DY-KFB常规开发板 |
CPU | STM32F407VG | ATMEG1284p |
CPU内核 | Cortex-M4 | 无 |
Flash | 1M | 128k |
SRAM | 192K | 16K |
EEPROM | 无 | 4k |
ADC | 12位、10位、8位、6位 | 10位 |
定时器 | 10个通用定时器;2个高级定时器;2个基本定时器 | 2个8位定时器;2个16位定时器 |
数据总线宽度 | 32位 | 8位 |
系统时钟频率 | 168M | 20M |
仿真器 | J-LINK | AVR JTAGICE |
换能器 | 200K以上 | 200K以下(含200K) |
5、文件部分源码
main.c文件代码#Include "stm32f4xx.h" #Include "main.h"
/* Private functions*/
void Delay(u32 nCount) //简单的延时函数
{
for(;nCount != 0; nCount--);
}
int main(void)
{
/*配置系统时钟RCC*/ SystemInit();
/*LED端口初始化*/ LED_GPIO_Config();
LED1(OFF);
LED2(OFF);
while(1)
{
LED1(ON);//亮
Delay(0xFFFFEF);
LED1(OFF); // 灭
LED2(ON);
Delay(0xFFFFEF);
LED2(OFF);
}
}
led.c文件代码#Include "led.h"
/*
* 函数名:LED_GPIO_Config
* 描述 :配置LED用到的I/O口
* 输入 :无
* 输出 :无
*/
void LED_GPIO_Config(void)//指示灯初始化
{
/*定义一个GPIO_InitTypeDef类型的结构体*/ GPIO_InitTypeDef GPIO_InitStructure;
/* 开 启 GPIOB 的 外 设 时 钟 */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/* 选 择 要 控 制 的 GPIOB 引 脚 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
/* 设 置 引 脚 模 式 为 通 用 输 出 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
/* 设 置 引 脚 模 式 为 推 挽 输 出 */ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
/* 设 置 引 脚 速 率 为 100MHz */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
/* 设 置 引 脚 没 有 上 拉 和 下 拉 */ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
/*调用库函数,初始化GPIOB*/ GPIO_Init(GPIOB, &GPIO_InitStructure);
}
实验2 中断检测按键
3、 用到的库文件startup_stm32f4xx.s system_stm32f4xx.c stm32f4xx_gpio.h stm32f4xx_rcc.h
stm32f4xx_exti.h stm32f4xx_syscfg.h misc.h
4、用户编写的文件main.c 和 main.h stm32f4xx_it.c led.c 和 led.h key.c 和 key.h delay.c和delay.h
5、 文件部分源码
main.c文件代码#Include "stm32f4xx.h"
#Include "main.h"
/*
* 函数名:main
* 描述 :主函数
* 输入 :无
* 输出 :无
*/
int main(void)
{
/*配置系统时钟RCC*/ SystemInit();
/*LED端口初始化*/ LED_GPIO_Config();
/*KEY端口初始化*/ Key_GPIO_Config();
EXTI_KEY_Config(KEY1);//按键1中断模式EXTI_KEY_Config(KEY2); EXTI_KEY_Config(KEY3);
LED1(ON);
LED2(ON);
while(1);
}
key.c文件代码#Include "key.h"
/*
* 函数名:Key_GPIO_Config
* 描述 :配置KEY用到的I/O口
* 输入 :无
* 输出 :无
*/
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_InitStructure);
}
/*
* 函数名:EXTI_KEY_Config
* 描述 :配置KEY用到的I/O口为中断口
* 输入 :无
* 输出 :无
*/
void EXTI_KEY_Config(Key_Def key)//将按键设置成中断方式
{
EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, KEY_PNS[key]);
EXTI_InitStructure.EXTI_Line = KEY_SRC[key]; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
if(key==KEY3)
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; else
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//嵌套分组为组0 NVIC_InitStructure.NVIC_IRQChannel = KEY_IRQ[key]; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
}
stm32f4xx_it.c部分文件代码void EXTI0_IRQHandler(void)
{
Delay(0x0FFFF); if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
LED1(OFF);//灭
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
void EXTI1_IRQHandler(void)
{
Delay(0x0FFFF); if(EXTI_GetITStatus(EXTI_Line1) != RESET)
{
LED2(OFF);
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
void EXTI3_IRQHandler(void)
{
Delay(0x0FFFF); if(EXTI_GetITStatus(EXTI_Line3) != RESET)
{ LED1(ON);
LED2(ON);
EXTI_ClearITPendingBit(EXTI_Line3);
}
}
实验3 12864液晶显示
3、 用到的库文件startup_stm32f4xx.s system_stm32f4xx.c stm32f4xx_gpio.h stm32f4xx_rcc.h stm32f4xx_syscfg.h misc.h
4、用户编写的文件
main.c 和main.h stm32f4xx_it.c delay.c和delay.h
lcd12864.c和 lcd12864.h
5、 文件部分源码
main.c部分文件代码
#Include "stm32f4xx.h" #Include "main.h"
/*
* 函数名:main
* 描述 :主函数
* 输入 :无
* 输出 :无
*/
int main(void)
{
/* 配置系统时钟RCC*/ SystemInit();
/* LCD端口初始化*/ LCD_12864_Config();
/* LCD复位*/ ResetLcd();
/* 清 屏 */ ClrScreen();
printFront(4,0,0);//距printFront(4,16,1);//离printFront(4,32,2);//: printNumbers(4,48,0);//0 printNumbers(4,56,0);//0 printNumbers(4,64,10);//. printNumbers(4,72,0);//0
printNumbers(4,80,0);//0 printFront(4,96,3);//厘printFront(4,112,4);//米
while(1);
}
lcd12864.c部分文件代码
#Include "lcd12864.h" #Include "delay.h"
void LCD_12864_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;//定义一个GPIO_InitStructure类型的结构体RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);//开启GPIOD的外设时钟
//GPIO_Pin_8控制LCDRES,GPIO_Pin_9控制LCDA0,GPIO_Pin_10控制LCDData6
,GPIO_Pin_11控制LCD Data7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 |GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_ResetBits(GPIOD, GPIO_Pin_3 |GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7); //输出低电平
}
/*********************************************************
- 功能描述:初始化LCD
- 隶属模块:公开函数模块
- 函数属性:
- 参数说明:
- 返回说明:
- 注:
*********************************************************/ void ResetLcd(void)
{
ClrRES;
delay_us(200);
SetRES; //2010.6.29增加以上三句,解决一体液晶屏经常花屏的问题delay_us(200);
Write_COM(Disp_Off);//Display OFF Write_COM(SetBias9);// 设置BIAS为1/9 Write_COM(ADC_Normal);//从左至右输入Write_COM(OUTNormal);//com1 --> com64
Write_COM(V5Ratio);// Select internal resistor ratio(Rb/Ra)mode
Write_COM(V5OutVol);// Set the v5 output voltage Write_COM(SetBright);//调节液晶屏的亮度
Write_COM(POWERSet);//voltage follower ON regulator ON booster ON Write_COM(DispNormal);// 从左至右显示
Write_COM(AllNormal);//Entire Display Disable
Write_COM(Disp_On);//Display ON ClrScreen();
Write_COM(SetStartLine);//Set Display Start Line = com0 Write_COM(SetPage);//Set Page Address = 0 Write_COM(SetColMsb);//Set Column Address = 0,set 4 higher bits
Write_COM(SetColLsb);//set 4 lower bits of column of display data RAM in register
}
/*********************************************************
- 功能描述:传递数据到LCD (串行)
- 隶属模块:公开函数模块
- 函数属性:
- 参数说明:
- 返回说明:
- 注:
*********************************************************/ void Write_SPI(uint8_t data)
{
uint8_t Count;
for (Count=0; Count<8; Count++)
{
if (data & 0x80)
{
}
else
{
}
Set_SI;
Clr_SI;
data <<= 1; Set_CLK; delay_us(1); Clr_CLK;
}
}
/*********************************************************
- 功能描述:写命令到LCD (串行)
- 隶属模块:公开函数模块
- 函数属性:
- 参数说明:
- 返回说明:
- 注:
*********************************************************/ void Write_COM(uint8_t cmdcode)
{
Clr_CLK; delay_us(1); ClrA0; delay_us(1); ClrCS1;
Write_SPI(cmdcode) ; SetCS1;
}
/*********************************************************
- 功能描述:写数据到LCD (串行)
- 隶属模块:公开函数模块
- 函数属性:
- 参数说明:
- 返回说明:
- 注:
*********************************************************/ void WriteData(uint8_t dispdata)
{
Clr_CLK; delay_us(1); SetA0; delay_us(1); ClrCS1;
Write_SPI(dispdata) ; SetCS1;
}
/*********************************************************
- 功能描述:清除LCD全屏
- 隶属模块:公开函数模块
- 函数属性:
- 参数说明:
- 返回说明:
- 注:
*********************************************************/ void ClrScreen(void)
{
uint8_t i, j;
Write_COM(SetStartLine);//Set Display Start Line = com0
for (i=0; i<8; i++)
{
Write_COM(SetPage+i); //Set Page Address
for (j=0; j<128; j++)
{
Write_COM(SetColLsb|(j&0x0f)); Write_COM(SetColMsb|((j&0xf0)>>4)); WriteData(0x00);
}
}
}
/*********************************************************
- 功能描述:在任意位置显示任意大小点阵
- 隶属模块:公开函数模块
- 函数属性:
- 参数说明:startCol起始*左列
startL起始*上端行**
*********************************************************/
void printNumbers(uint8_t startL,uint8_t startCol,int16_t code)//输入阿拉伯数字 8*16 字模
{
uint8_t col;
Write_COM(0x10+(startCol>>4)); Write_COM(startCol&0x0f); Write_COM(0xB0+startL); for(col = 0; col < 8; col++)
{
WriteData(LcdFont[code][col]);
}
Write_COM(0x10+(startCol>>4)); Write_COM(startCol&0x0f); Write_COM(0xB0+startL-1); for(col = 0; col < 8; col++)
{
WriteData(LcdFont[code][col+8]);
}
}
void printFront(uint8_t startL,uint8_t startCol,int16_t uChar) //输入字 16*16 字模
{
uint8_t col;
Write_COM(0x10+(startCol>>4)); Write_COM(startCol&0x0f); Write_COM(0xB0+startL); for(col = 0; col < 16; col++)
{
WriteData(Font[uChar][col]);
}
Write_COM(0x10+(startCol>>4)); Write_COM(startCol&0x0f); Write_COM(0xB0+startL-1); for(col = 0; col < 16; col++)
{
WriteData(Font[uChar][col+16]);
}
}
实验4 异步串行口(USART)的简单应用
3、 用到的库文件startup_stm32f4xx.s system_stm32f4xx.c stm32f4xx_gpio.h stm32f4xx_rcc.h stm32f4xx_usart.h
misc.h
4、用户编写的文件main.c 和 main.h stm32f4xx_it.c delay.c和delay.h usart.c 和 usart.h led.c和 led.h
5、 文件部分源码
main.c部分文件代码#Include "stm32f4xx.h"
#Include "main.h" uint16_t temp;
int main(void)
{
/*配置系统时钟RCC*/ SystemInit();
/*LED端口初始化*/ LED_GPIO_Config();
/*USART端口初始化*/ USART_Config(); NVIC_USART_Config();
LED1(OFF);
LED2(OFF);
temp=0;
while(1)
{
USART1_Puts("Hello Wrold!\n"); LED1(ON);
Delay(0xFFFFFF); LED1(OFF);
//while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==RESET);
//串口是否接受到数据
Delay(0xFFFFFF); LED2(OFF);
USART1_Puts("Get Data From USART1:"); temp = USART_ReceiveData(USART1); USART_SendData(USART1,temp);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
//串口发送是否完成
Delay(0xFFFFFF); USART1_Puts("\r\n");
}
}
usart.c部分文件代码#Include "usart.h"
/************************************************* Function: void USART_Config(void)
Description: USART配置函数Input: 无
Output:无Return:无
*************************************************/ void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; USART_ClockInitTypeDef USART_ClockInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启USART1时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //开启GPIOA时钟GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,
GPIO_AF_USART1);//这相当于M3的开启复用时钟?只配置复用的引脚, GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);//
GPIO_StructInit(&GPIO_InitStructure);//缺省值填入
/* 配 置 GPIOA_Pin9 为 TX 输 出 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;//设置为复用,必须为AF,OUT不行GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd= GPIO_PuPd_NOPULL; //没有上拉和下拉GPIO_InitStructure.GPIO_OType= GPIO_OType_PP;//输出推免GPIO_Init(GPIOA,&GPIO_InitStructure);
/* 配 置 GPIOA_Pin10 为 RX 输 入 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;//这也必须为复用,与M3不同!
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure);
/*配置USART1*/
USART_StructInit(&USART_InitStructure);// 这 个 要 屏 蔽 是 不 行 的 2014.3.20 USART_InitStructure.USART_BaudRate =115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl=
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure);
/* Enable USART */
USART_ClockStructInit(&USART_ClockInitStruct);//填充外设时钟默认值USART_ClockInit(USART1, &USART_ClockInitStruct); //初始化外设时钟USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//使能 USART1中断USART_Cmd(USART1, ENABLE);//使能 USART1
}
void NVIC_USART_Config()
{
NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 嵌 套 优 先 级 分 组 为 1 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //嵌套通道为USART1_IRQn NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级为 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //响应优先级为 0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //通道中断使能NVIC_Init(&NVIC_InitStructure);
}
/************************************************* Function: void USART1_Puts(char * str)
Description: USART1发送数据Input: 待发送数据指针Output:无
Return:无
*************************************************/ void USART1_Puts(char * str)
{
while (*str)
{
USART_SendData(USART1, *str++);
/* Loop until the end of transmission */
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
//当TXE被置起时,一帧数据传输完成
}
}
stm32f4xx_it.c部分文件代码
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判断为接收中断
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除中断挂起位USART_SendData(USART1, USART_ReceiveData(USART1)); //发送收到的数据while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); LED2(ON); //点亮LED,起到中断指示作用
}
}
实验5 PWM输出
3、 用到的库文件startup_stm32f4xx.s system_stm32f4xx.c stm32f4xx_gpio.h stm32f4xx_rcc.h stm32f4xx_tim.h misc.h
4、用户编写的文件
main.c 和main.h stm32f4xx_it.c ssp.c和ssp.h
5、 文件部分源码
main.c部分文件代码#Include "stm32f4xx.h"
#Include "main.h"
/* Private functions*/
int main(void)
{
uint32_t i=0;
//配置系统时钟RCC SystemInit(); NVIC_Config(); GPIO_Config();
SSP_Configuration(); // 配置TIM2的脉冲输出为10Hz
while(1)
{
if(TIM2_Pulse_TIM3_Counter_OK == 0) Output_Pulse(PulseNum);
else if(TIM2_Pulse_TIM3_Counter_OK == 1)
{
for(i=0; i<; i++);// Delay TIM2_Pulse_TIM3_Counter_OK = 0;
}
}
}
ssp.c部分文件代码
#Include "ssp.h"
uint8_t TIM2_Pulse_TIM3_Counter_OK = 0;
/*
* 函数名:TIM1_GPIO_Config
* 描述 :配置TIM1复用输出PWM时用到的I/O
* 输入 :无
* 输出 :无
*/
void GPIO_Config(void)
{
/*定义了一个GPIO_InitStructure的结构体,方便一下使用 */ GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA , ENABLE);
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3, ENABLE);
/* Timer2 Channel 1, PA0 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_TIM2);
}
void SSP_Configuration(void)
{
uint16_t nPDTemp ;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2|RCC_APB1Periph_TIM3, ENABLE);
TIM_Cmd(TIM2, DISABLE);
nPDTemp = /PulseFrequency;
// 时基配置:配置PWM输出定时器——TIM2
// Time base configuration TIM_TimeBaseStructure.TIM_Period = nPDTemp - 1; TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
// 输出配置:配置PWM输出定时器——TIM2
// PWM1 Mode configuration: Channel1 TIM_OCInitStructure.TIM_Pulse = nPDTemp >> 1;//50% TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OC2Init(TIM2, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2, ENABLE);
// 时基配置:配置脉冲计数寄存器——TIM3 TIM_TimeBaseStructure.TIM_Period = 0xFFFF; TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// Output Compare Active Mode configuration: Channel1 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0xFFFF; // 这里的配置值意义不大TIM_OC1Init(TIM3, &TIM_OCInitStructure);
// 配置TIM2为主定时器
// Select the Master Slave Mode
TIM_SelectMasterSlaveMode(TIM2, TIM_MasterSlaveMode_Enable);
// Master Mode selection
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);
// 配置TIM3为从定时器
// Slave Mode selection: TIM3 TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Gated);
TIM_SelectInputTrigger(TIM3, TIM_TS_ITR1); TIM_ITRxExternalClockConfig(TIM3, TIM_TS_ITR1);
//TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE);
TIM_Cmd(TIM2, DISABLE); TIM_Cmd(TIM3, DISABLE);
TIM_CtrlPWMOutputs(TIM2, ENABLE);//使能TIM2的PWM输出,
}
void Output_Pulse(u16 Num)
{
TIM3->CCR1 = Num;
TIM3->CNT = 0;
TIM_Cmd(TIM3, ENABLE); TIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); TIM_Cmd(TIM2, ENABLE);
TIM2_Pulse_TIM3_Counter_OK = 1;
}
//==============================
//
// 配置中断向量表及优先级
//
//==============================
void NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
#Ifdef VECT_TAB_RAM NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); #Else
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); #Endif
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
}
实验6ADC采集数据(采用DMA模式)
3、 用到的库文件startup_stm32f4xx.s system_stm32f4xx.c stm32f4xx_gpio.h stm32f4xx_rcc.h stm32f4xx_tim.h stm32f4xx_adc.h stm32f4xx_dma.h misc.h
4、用户编写的文件main.c 和 main.h stm32f4xx_it.c ssp.c和ssp.h
adc.c和adc.h
5、 文件部分源码
main.c部分文件代码#define LONGSAMPNUM100
uint16_t DATASMOOTH[LONGSAMPNUM]={0};
/* Private functions*/
int main(void)
{
uint32_t i=0;
//配置系统时钟RCC SystemInit(); NVIC_Config(); GPIO_Config();
SSP_Configuration(); // 配置TIM2的脉冲输出
ADC3_GPIO_Config(); ADC3_Mode_Config(); ADC_SoftwareStartConv(ADC3); while(1)
{
if(TIM2_Pulse_TIM3_Counter_OK == 0) Output_Pulse(PulseNum);
else if(TIM2_Pulse_TIM3_Counter_OK == 1)
{
for(i=0; i<; i++);// Delay TIM2_Pulse_TIM3_Counter_OK = 0;
}
ProceAD(DATASMOOTH,LONGSAMPNUM);
}
}
adc.c部分文件代码#Include "adc.h"
IO uint16_t ADC3ConvertedValue = 0;
/*
* 函数名:ADC1_GPIO_Config
* 描述 :使能ADC1和DMA1的时钟,初始化PC.01
* 输入 : 无
* 输出 :无
* 调用 :内部调用
*/
void ADC3_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Configure PC.01 as analog input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure);//
PC1,输入时不用设置速率
}
/* 函数名:ADC1_Mode_Config
* 描述 :配置ADC1的工作模式为MDA模式
* 输入 : 无
* 输出 :无
* 调用 :内部调用
*/
void ADC3_Mode_Config(void)
{//AD初始化
ADC_InitTypeDefADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDefDMA_InitStructure;
/* Enable ADC3, DMA2 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
/* DMA2 Stream0 channel0 configuration **************************************/ DMA_InitStructure.DMA_Channel = DMA_Channel_2; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 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_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream0, ENABLE);
/* ADC Common Init **********************************************************/ ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 Init ****************************************************************/ ADC_StructInit(& ADC_InitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC3, &ADC_InitStructure);
/* ADC3 regular channel12 configuration *************************************/ ADC_RegularChannelConfig(ADC3, ADC_Channel_2, 1, ADC_SampleTime_3Cycles);
/* Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
/* Enable ADC3 DMA */ ADC_DMACmd(ADC3, ENABLE);
/* Enable ADC3 */ ADC_Cmd(ADC3, ENABLE);
}
void ProceAD(uint16_t *ADIn,uint32_t ADLen)
{
while(ADLen>0)
{
*ADIn = ADC3ConvertedValue;
ADIn++;//调整指针
ADLen--;
}
}
3、 用到的库文件startup_stm32f4xx.s system_stm32f4xx.c stm32f4xx_gpio.h stm32f4xx_rcc.h stm32f4xx_syscfg.h stm32f4xx_adc.h stm32f4xx_dma.h
4、用户编写的文件main.c 和 main.h stm32f4xx_it.c delay.c和delay.h mf58.c和 mf58.h
5、 文件部分源码
#Include "main.h"
/*
* 函数名:main
* 描述 :主函数
* 输入 :无
* 输出 :无
*/
int main(void)
{
double okdata;
uint16_t num1,num2,num3,num4; uint32_t numdata;
/*配置系统时钟RCC*/ SystemInit();
/*LCD端口初始化*/ LCD_12864_Config();
/*LCD复位*/ ResetLcd();
/*清屏*/ ClrScreen();
ADC1_GPIO_Config(); ADC1_Mode_Config(); ADC_SoftwareStartConv(ADC1);
while(1)
{
Temperature = GetTemp(); okdata = Temperature; okdata = okdata *100; numdata = okdata;
num1 = numdata / 1000; numdata = numdata % 1000; num2 = numdata / 100; numdata = numdata % 100; num3 = numdata / 10;
num4 = numdata % 10;
printFront(4,0,0);//温printFront(4,16,1);//度printFront(4,32,2);//: printNumbers(4,48,num1);//0 printNumbers(4,56,num2);//0
printNumbers(4,64,10);//. printNumbers(4,72,num3);//0 printNumbers(4,80,num4);//0 printFront(4,96,3);//℃ Delay(0xFFFFEF); Delay(0xFFFFEF);
}
}
Mf58.c部分文件代码#Include "mf58.h"
#Include "math.h" #Include "arm_math.h"
IO uint16_t ADC1ConvertedValue = 0;
/*
* 函数名:ADC1_GPIO_Config
* 描述 :使能ADC1和DMA1的时钟,初始化PC.01
* 输入 : 无
* 输出 :无
* 调用 :内部调用
*/
void ADC1_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Configure PC.01 as analog input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure);//
PC1,输入时不用设置速率
}
/* 函数名:ADC1_Mode_Config
* 描述 :配置ADC1的工作模式为MDA模式
* 输入 : 无
* 输出 :无
* 调用 :内部调用
*/
void ADC1_Mode_Config(void)
{//AD初始化
ADC_InitTypeDefADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDefDMA_InitStructure;
/* Enable ADC3, DMA2 and GPIO clocks ****************************************/ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 , ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
/* DMA2 Stream0 channel0 configuration **************************************/ DMA_InitStructure.DMA_Channel=DMA_Channel_0;
//通道为2(根据芯片资料查找)
DMA_InitStructure.DMA_PeripheralBaseAddr= (uint32_t)ADC1_DR_ADDRESS;//ADC3的数据寄存器地址(根据芯片资料查找)
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue; DMA_InitStructure.DMA_DIR=
DMA_DIR_PeripheralToMemory;//数据传输方向:从外设到内存DMA_InitStructure.DMA_BufferSize = 1;//缓存器大小:1个单位DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//禁止外设地址自加DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//禁止内存地址自加DMA_InitStructure.DMA_PeripheralDataSize=
DMA_PeripheralDataSize_HalfWord;//外设数据宽度:16位DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
//内存数据宽度:16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA模式:循环模式DMA_InitStructure.DMA_Priority = DMA_Priority_High; //优先级:高DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;//FIFO禁止使用DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream0, ENABLE);
/* ADC Common Init **********************************************************/ ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent;
//AD执行模式:独立模式
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; //时钟预分频:2分频ADC_CommonInitStructure.ADC_DMAAccessMode=
ADC_DMAAccessMode_Disabled;//这个是用于多通道模式,所以此处选择禁止
//ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
//两次采样之间延时5个时钟周期
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_10Cycles; ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC3 Init ****************************************************************/ ADC_StructInit(& ADC_InitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//AD转换的位数为12位ADC_InitStructure.ADC_ScanConvMode=DISABLE;
//SCAN模式用于多路同时采集,此处选择禁止ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //允许循环采集ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None;
//无外部触发源
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据对齐方式:右对齐ADC_InitStructure.ADC_NbrOfConversion = 1; //采集通道数:1个通道ADC_Init(ADC1, &ADC_InitStructure);
/* ADC3 regular channel12 configuration *************************************/
// ADC_RegularChannelConfig(ADC3, ADC_Channel_3, 1, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_480Cycles);
/* Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC3 DMA */ ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC3 */ ADC_Cmd(ADC1, ENABLE);
}
double GetTemp(void)
{
uint16_t Temp[10]; uint16_t AverTemp; uint16_t Temp_T; uint8_t i,j;
double Temp_Value; double AverTemp1; double RT;
Temp_Value = 0;
AverTemp = 0;
AverTemp1 =0; RT=0;
Temp_T =0;
for(i=0;i<10;i++)
Temp[i] =0;
for(i=0;i<10;i++)//连续24次AD采样
{
Temp[i] = ADC1ConvertedValue;
}
for(i = 0;i<10;i++)//把AD采样值排序
{
for(j=0;j<10-i;j++)
{
if(Temp[j] >= Temp[j+1]) Temp_T =Temp[j]; Temp[j] = Temp[j+1]; Temp[j+1] = Temp_T;
}
}
for(i = 1;i<9;i++)//去处*小的四个,*的四个,进行平均AverTemp += Temp[i];
AverTemp >>= 3;
AverTemp1=(AverTemp*3.3)/4096.0;
RT=(AverTemp1*10000)/(3.3- AverTemp1)-1000;//2012.11.22要减去串到温度中的1K电阻Temp_Value=1/((log(RT/5000))/3470+1/298.15)-273.15;
if( (Temp_Value<(-45.0) )|| ( Temp_Value>105.0))//超出温度范围Temp_Value=15.0;
return Temp_Value;
}
实验7 利用*实现测距功能
综述:我司的开发板+换能器(测距型)实现测距显示功能是通过单片机在PA1口输出与换能器同频的P WM信号(反向的),经过反向,放大升压成实际的驱动换能器的信号,信号在空间传输碰到被测物体反射回来,被换能器接收到,经过放大后从PA2口进入单片机。我们通过AD采样获取到信号后,通过阀值判断出发射波和回波,得出时间间隔t,由s=1/2*V*t计算出距离。
1、换能器
我们换能器又称超声波探头,主要由压电陶瓷构成,既可以发射声波又可以接受声波。在接受到高频电压驱动信号时,压电陶瓷产生振动,激励周围空气质点产生振动,由于空气具有惯性和弹性,在空气质点的相互作用下,振动物体周围的空气就交替地产生压缩与膨胀,并且逐渐向外传播而形成声波。(反之, 声波信号传到换能器时,换能器会输出电压信号)。
换能器盲区:发射波和回波能明显分开的*小距离
换能器信号拖尾:高频驱动电压结束后,换能器的振动不能立即停止,在驱动信号后就会产生拖尾(实际发射波数量大于驱动信号的数量)
探头的指向性:有小角度的(例如半功率角@-3dB:4.1°±1,锐度角9.7°±2)适用于测距也有水平无方向的,不适用与单向测距
2、硬件信号(以空气中300K换能器为例) 开发板需要用户自行外接24V电源。
在TP1测试电是5V电源信号在TP2测试点是3.3V电源信号
首先单片机在PA1口产生一定数量的(一般1-50个脉冲)3.3V的反向PWM信号
信号经过反向放大后在TP3可测的信号5V正向脉冲信号(因为极间电容,信号有所变形)
自发自收信号通过TRANS过来经过限幅(双探头从J2过来)经过3级管,带通滤波一级放大后可在
TP5点测的信号
再经过带通滤波第二级放大,可在TP6点上测的信号
默认采用A/D采样方式2,经过AD8310放大整形成单向包罗信号,再由LM358运放放大后可在TP7点测的信号
补充说明:使用小于200K的换能器时,驱动电压会达到800多V
使用不同的探头的,在不同的距离下,信号的幅度,发射波和回波的时间差,以及盲区会有所差异,以实测为准
使用水平无方向的换能器是不能正确测量距离的。
AD采样方式1是经过rc滤波后通过比较器,输出脉冲信号的。大于阈值的输出高电平,小于阈值的输出低电平,可通过调节可调电阻改变比较器的阈值。这个信号留给客户自行发挥。
3软件
我们的简易测距代码是通过在PA1口输出PWM,在PA2通过(在一定的采样周期)AD采样获取发射波和回波的信号放在一个数组里。通过判断回波幅度(阈值法)判断发射波和回波的所在位置,有点数乘以采样周期的出发射波和回波的时间差,再乘以声速得出距离值。