采用查询发送和接收中断的方式与PC机进行通信,PC输入指令控制LED。很常见的串口通信,唯一有的意思的是读取串口接收信息的时候采用提取关键字的方法,只要你的串口信息中包括这几个关键字就能控制相关操作。如下:
1、上位机发送open1*(其中'*'号是指令结束标志)指令——打开LED1,单片机向上位机返回OpenedLED1信息。
2、上位机发送close1*(其中'*'号是指令结束标志)指令——关闭LED1,单片机向上位机返回ClosedLED1信息。
3、上位机发送openall*(其中'*'号是指令结束标志)指令——打开所有LED,单片机向上位机返回Opened All信息。
4、上位机发送closeall*(其中'*'号是指令结束标志)指令——打开所有LED,单片机向上位机返回Closed All信息。
5、上位机发送open1,open2,close3*(其中'*'号是指令结束标志)指令——打开所有LED1、LED2;关闭LED3,单片机向上位机返回OpenedLED1、OpenedLED2、ClosedLED3信息。
6、也可以发送dfhasjkfhopen1*(包含了open1*)信息打开LED1。
7、发送xdfklgjdflkopen1open27&#close3* 信息和第五步的效果是一样的。
工程文件包下载http://share.eepw.com.cn/share/download/id/71062
IAR ARM V 6.3
设计要求:
1、通过网页控制开关4个LED;
2、在网页上显示出2路AD的电压值,以及温度传感器的温度,应该DMA读取ADC的值,并进行多次取值求均值;
3、串口打印相关调试信息;
4、通过页面设置ARM_WebServer的IP,并储存在EEPROM2402中;
完成情况:
1、通过网页控制开关4个LED;——完成
2、在网页上显示出2路AD的电压值,以及温度传感器的温度,应该DMA读取ADC的值,并进行多次取值求均值;——完成
3、串口打印相关调试信息;——完成
4、通过页面设置ARM_WebServer的IP,并储存在EEPROM2402中;——未完成(硬件I2C,果断的死循环了)
实物图
ADC、DMA、USAT和TIM的综合使用
3路ADC分别是通道12,13,16,进行连续多通道扫描;通道16为内部温度传感器;通过DMA进行循环模式读取。通过TIM2进行1.5s的中断定时,USART1则1.5s把数据发送出去。ADC多次抽样求均值。
/*******************STM32 ADC初始化过程**********************
步骤1:GPIO初始化 ——RCC_APB2PeriphClockCmd,使能APB2外设时钟
——GPIO_Init,初始化GPIOx寄存器
步骤2:ADC初始化 ——ADC_Init,初始化外设ADCx的寄存器
——ADC_RegularChannelConfig,设置组通道、顺序和采样时间
——ADC_Cmd,使能ADC
——ADC_SoftwareStartConvCmd,使能ADC软件转换启动功能
步骤3:ADC自动校准——ADC_ResetCalibration,重置ADC校准寄存器
——ADC_GetResetCalibrationStatus,获取ADC重置寄存器的状态
——ADC_StartCalibration,开始指定ADC的校准程序
——ADC_GetCalibrationStatus,获取指定ADC的校准状态
这样的步骤就不会造成DMA取值的混乱。
部分函数程序:
void ADC_DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA1 channel1 configuration ----------------------------------------------*/
//将DMA的通道1重设为缺省值
DMA_DeInit(DMA1_Channel1);
//DMA对应的外设地址
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)ADC1_DR_Address;
/*定义DMA通道存储器地址
定义数组vu16 AD_Value[3]
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)AD_Value; */
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&AD_Value;
/*指定外设存储器为源地址
DMA_DIR_PeripheralDRC:外设目标
DMA_DIR_PeripheralSRC:外设是数据源 */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/*定义DMA缓存大小(0~65535),小于或等于内存缓存区的大小;
只能在通道不工作是写入,通道开启后变为只读,寄存器内容在每次DMA传输后递减;
数据传输结束后变为0,或者自动重载为之前的配置的数值;
当为0时,无论通道是否开启,都不会发生数据的传输。 */
DMA_InitStructure.DMA_BufferSize = N*M;
/*外设寄存器地址变化模式;
DMA_PeripheralInc_Enable:递增模式
DMA_PeripheralInc_Disable:非递增模式 */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
/*设置DMA内存地址变化模式
DMA_MemoryInc_Enable:递增模式
DMA_MemoryInc_Disable:非递增模式 */
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*定义外设数据宽度,每次操作时外设数据的位宽度
Byte:8位;HalfWord:16位;Word:32位 */
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
/*定义储存器的宽度,每次操作时内存数据的位宽度
Byte:8位;HalfWord:16位;Word:32位 */
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/*设置DMA传输模式
DMA_Mode_Circular:循环模式;用于处理循环缓冲区和连续的数据传输;自动重载配置时的数值
DMA_Mode_Normal:非循环模式 */
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/*设置优先级,分四级。
VeryHigh; High; Medium; Low; */
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/*DMA通道的M2M传输模式
DMA_M2M_Enable:启动存储器到存储器模式,可以在没有外设请求的情况下进行,此模式下不能与循环模式同时使用
DMA_M2M_Disable:启动费存储器到存储器 */
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
// 初始化
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
void ADC1_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
/* ADC1 configuration ------------------------------------------------------*/
/*工作模式设置
Independent ADC1和ADC2工作在独立模式
RegInjecSimult ADC1和ADC2工作在同步规则和同步注入模式
RegSimult_AlterTrig ADC1和ADC2工作在同步规则和交替触发模式
InjecSimult_FasInterl ADC1和ADC2工作在同步规则和快速交替模式
InjecSimult_SlowInterl ADC1和ADC2工作在同步规则和慢速交替模式
InjecSimult ADC1和ADC2工作在同步注入模式
RegSimult ADC1和ADC2工作在同步规则模式
FasInterl ADC1和ADC2工作在快速交替模式
SlowInterl ADC1和ADC2工作在慢速交替模式
AlterTrig ADC1和ADC2工作在交替触发模式 */
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
/*扫描工作模式——ENABLE:多通道;DISABLE:单通道 */
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //使能连续多通道
/*连续工作模式——ENABLE:连续转换;DISABLE:单次转换 */
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //使能连续转换
/*转换触发方式——ENABLE:连续转换;DISABLE:单次转换 */
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfChannel = M; //扫描通道数
ADC_Init(ADC1, &ADC_InitStructure);
ADC_TempSensorVrefintCmd(ENABLE); //启动温度传感器
/* ADC1 信道1的转换通道14的采样时间设置为ADC_SampleTime_55Cycles5 */
ADC_RegularChannelConfig(ADC1, ADC_Channel_12, 1, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 2, ADC_SampleTime_239Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 3, ADC_SampleTime_239Cycles5);
/* 使能或者失能ADC的DMA请求 */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* 重置ADC的校准寄存器 */
ADC_ResetCalibration(ADC1);
/* 获取ADC重置校准寄存器状态 */
while(ADC_GetResetCalibrationStatus(ADC1));
/* 开始校准程序 */
ADC_StartCalibration(ADC1);
/* 获取校准状态*/
while(ADC_GetCalibrationStatus(ADC1));
/* 使能或失能ADC的软件转换启动功能 */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}
void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Prescaler configuration */
TIM_PrescalerConfig(TIM2, 36000, TIM_PSCReloadMode_Immediate);
/* Output Compare Timing Mode configuration: Channel1 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
}
u8 * print_decimal ( u8 *ptr, u8 digit, u16 dec )
{
if ( digit >= 5 )
*ptr++ = ( (dec/10000) + '0' );
if ( digit >= 4 )
*ptr++ = ( ((dec%10000)/1000) + '0' );
if ( digit >= 3 )
*ptr++ = ( ((dec%1000)/100) + '0' );
if ( digit >= 2 )
*ptr++ = ( ((dec%100)/10) + '0' );
*ptr++ = ( ((dec%10)) + '0' );
return ptr;
}
u16 GetTemp(u16 advalue)
{
u32 Vtemp_sensor;
s32 Current_Temp;
// ADC转换结束以后,读取ADC_DR寄存器中的结果,转换温度值计算公式如下:
// V25 - VSENSE
// T(℃) = ------------ + 25
// Avg_Slope
// V25: 温度传感器在25℃时 的输出电压,典型值1.43 V。
// VSENSE:温度传感器的当前输出电压,与ADC_DR 寄存器中的结果ADC_ConvertedValue之间的转换关系为:
// ADC_ConvertedValue * Vdd
// VSENSE = --------------------------
// Vdd_convert_value(0xFFF)
// Avg_Slope:温度传感器输出电压和温度的关联参数,典型值4.3 mV/℃。
Vtemp_sensor = ((vu32)advalue )* 3300>>12 ; //工作电压3.3伏.
Current_Temp = 250 +(1430-(vu16)Vtemp_sensor)*100/43;
return (s16)Current_Temp;
}
u16 GetVolt(u16 advalue)
{
return (u16)(advalue * 330 / 4096);
}
可执行文件下载地址:http://share.eepw.com.cn/share/download/id/76087
视频奉上:
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图四被打赏50分 | |
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 |