1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
刚开始学习STM32,用的是开发板是野火的指南者,这款板子网上资源很多。在学习ADC和LCD部分时,想利用手头仅有的LCD1602A进行显示电压,借助原有例程,经过不断调试后,就有如下代码(仅做交流学习)。 代码 main.c #include "stm32f10x.h" #include "bsp_SysTick.h" #include "bsp_lcd1602a.h" #include "bsp_adc.h" #include extern __IO uint16_t ADC_ConvertedValue; // 局部变量,用于保存转换计算后的电压值 float ADC_ConvertedValueLocal; int main(void) { uint8_t a[10]; USART_Config(); // ADC 初始化 ADCx_Init(); /*LCD1602A初始化*/ Lcd_Init(); Lcd1602a_ClearScreen(); Lcd1602a_Disp_Strs(0, 0, "voltage="); Lcd1602a_Disp_Strs(14, 1, "V"); while(1) { ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/4096*3.3; sprintf(a,"%5.3f",ADC_ConvertedValueLocal); Lcd1602a_Disp_Strs(7, 1, a); SysTick_Delay_Ms(1000); //一秒刷新一次 } 这里的参数可以根据自己意愿调整字符显示位置,不过LCD1602A只有两行。这里运用了sprintf函数,这个函数可以将ADC获取的数据转化为字符串,具体用法可自行百度。 bsp_adc.h #ifndef __ADC_H #define __ADC_H #include "stm32f10x.h" // ADC 编号选择 // 可以是 ADC1/2,如果使用ADC3,中断相关的要改成ADC3的 #define ADC_APBxClock_FUN RCC_APB2PeriphClockCmd #define ADCx ADC2 #define ADC_CLK RCC_APB2Periph_ADC2 // ADC GPIO宏定义 // 注意:用作ADC采集的IO必须没有复用,否则采集电压会有影响 #define ADC_GPIO_APBxClock_FUN RCC_APB2PeriphClockCmd #define ADC_GPIO_CLK RCC_APB2Periph_GPIOC #define ADC_PORT GPIOC #define ADC_PIN GPIO_Pin_1 // ADC 通道宏定义 #define ADC_CHANNEL ADC_Channel_11 void ADCx_Init(void); #endif /* __ADC_H */ 这里的ADC通道和引脚可以根据数据手册进行自定义更改。 bsp_adc.c #include "bsp_adc.h" __IO uint16_t ADC_ConvertedValue; //ADC GPIO初始化 static void ADCx_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // 打开 ADC IO端口时钟 ADC_GPIO_APBxClock_FUN ( ADC_GPIO_CLK, ENABLE ); // 配置 ADC IO 引脚模式 // 必须为模拟输入 GPIO_InitStructure.GPIO_Pin = ADC_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 初始化 ADC IO GPIO_Init(ADC_PORT, &GPIO_InitStructure); } //配置ADC工作模式 static void ADCx_Mode_Config(void) { ADC_InitTypeDef ADC_InitStructure; // 打开ADC时钟 ADC_APBxClock_FUN ( ADC_CLK, ENABLE ); // ADC 模式配置 // 只使用一个ADC,属于独立模式 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 禁止扫描模式,多通道才要,单通道不需要 ADC_InitStructure.ADC_ScanConvMode = DISABLE ; // 连续转换模式 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 不用外部触发转换,软件开启即可 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 转换结果右对齐 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 转换通道1个 ADC_InitStructure.ADC_NbrOfChannel = 1; // 初始化ADC ADC_Init(ADCx, &ADC_InitStructure); // 配置ADC时钟为PCLK2的8分频,即9MHz RCC_ADCCLKConfig(RCC_PCLK2_Div8); // 配置 ADC 通道转换顺序和采样时间 ADC_RegularChannelConfig(ADCx, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5); // ADC 转换结束产生中断,在中断服务程序中读取转换值 ADC_ITConfig(ADCx, ADC_IT_EOC, ENABLE); // 开启ADC ,并开始转换 ADC_Cmd(ADCx, ENABLE); // 初始化ADC 校准寄存器 ADC_ResetCalibration(ADCx); // 等待校准寄存器初始化完成 while(ADC_GetResetCalibrationStatus(ADCx)); // ADC开始校准 ADC_StartCalibration(ADCx); // 等待校准完成 while(ADC_GetCalibrationStatus(ADCx)); // 由于没有采用外部触发,所以使用软件触发ADC转换 ADC_SoftwareStartConvCmd(ADCx, ENABLE); } static void ADC_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; // 优先级分组 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); // 配置中断优先级 NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void ADCx_Init(void) { ADCx_GPIO_Config(); ADCx_Mode_Config(); ADC_NVIC_Config(); } bsp_lcd1602a.h #ifndef __BSP_LCD1602A_H #define __BSP_LCD1602A_H #include "stm32f10x.h" #include "bsp_SysTick.h" //以下引脚根据开发板的引脚自行设置好:1.时钟 2.GPIOx 3.引脚号 //RS --> data/cmd select io #define LCD1602A_RS_CLK RCC_APB2Periph_GPIOB #define LCD1602A_RS_PORT GPIOB #define LCD1602A_RS_PIN GPIO_Pin_5 //R/W --> write/read select io #define LCD1602A_RW_CLK RCC_APB2Periph_GPIOB #define LCD1602A_RW_PORT GPIOB #define LCD1602A_RW_PIN GPIO_Pin_6 //E --> en flag #define LCD1602A_E_CLK RCC_APB2Periph_GPIOB #define LCD1602A_E_PORT GPIOB #define LCD1602A_E_PIN GPIO_Pin_7 /********8'bit data line***************/ //D0 #define LCD1602A_D0_CLK RCC_APB2Periph_GPIOB #define LCD1602A_D0_PORT GPIOB #define LCD1602A_D0_PIN GPIO_Pin_0 //D1 #define LCD1602A_D1_CLK RCC_APB2Periph_GPIOC #define LCD1602A_D1_PORT GPIOC #define LCD1602A_D1_PIN GPIO_Pin_13 //D2 #define LCD1602A_D2_CLK RCC_APB2Periph_GPIOE #define LCD1602A_D2_PORT GPIOE #define LCD1602A_D2_PIN GPIO_Pin_5 //D3 #define LCD1602A_D3_CLK RCC_APB2Periph_GPIOA #define LCD1602A_D3_PORT GPIOA #define LCD1602A_D3_PIN GPIO_Pin_6 //D4 #define LCD1602A_D4_CLK RCC_APB2Periph_GPIOA #define LCD1602A_D4_PORT GPIOA #define LCD1602A_D4_PIN GPIO_Pin_4 //D5 #define LCD1602A_D5_CLK RCC_APB2Periph_GPIOB #define LCD1602A_D5_PORT GPIOB #define LCD1602A_D5_PIN GPIO_Pin_1 //D6 #define LCD1602A_D6_CLK RCC_APB2Periph_GPIOB #define LCD1602A_D6_PORT GPIOB #define LCD1602A_D6_PIN GPIO_Pin_8 //D7 #define LCD1602A_D7_CLK RCC_APB2Periph_GPIOC #define LCD1602A_D7_PORT GPIOC #define LCD1602A_D7_PIN GPIO_Pin_6 //SETTING BIT AND STATS #define LCD1602A_RS_SET GPIO_SetBits(LCD1602A_RS_PORT, LCD1602A_RS_PIN) #define LCD1602A_RS_CLR GPIO_ResetBits(LCD1602A_RS_PORT, LCD1602A_RS_PIN) #define LCD1602A_RW_SET GPIO_SetBits(LCD1602A_RW_PORT, LCD1602A_RW_PIN) #define LCD1602A_RW_CLR GPIO_ResetBits(LCD1602A_RW_PORT, LCD1602A_RW_PIN) #define LCD1602A_E_SET GPIO_SetBits(LCD1602A_E_PORT, LCD1602A_E_PIN) #define LCD1602A_E_CLR GPIO_ResetBits(LCD1602A_E_PORT, LCD1602A_E_PIN) /*all_define*/ #define LCD1602A_CMD_LINE_CLK LCD1602A_RS_CLK | LCD1602A_RW_CLK | LCD1602A_E_CLK #define LCD1602A_DATA_LINE_CLK LCD1602A_D0_CLK | LCD1602A_D1_CLK | LCD1602A_D2_CLK | LCD1602A_D3_CLK | LCD1602A_D4_CLK | LCD1602A_D5_CLK | LCD1602A_D6_CLK | LCD1602A_D7_CLK /*sel_write_operation_mode*/ typedef enum {Com = 0, Data = !Com} SelectStatus; #define MODE_GPIO GPIO_Mode_Out_PP /*function mode*/ void Lcd_Write_State(SelectStatus Com_or_Data, uint8_t Write_Data); void BSP_GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, SelectStatus BitVal); void BSP_GPIO_Write(uint8_t Data); void Lcd_Write_State(SelectStatus Com_or_Data, uint8_t Write_Data); void Lcd_Init(void); void Lcd1602a_ClearScreen(void); void Lcd1602a_Set_Cursor(uint8_t x, uint8_t y); void Lcd1602a_Disp_One_Str(uint8_t x, uint8_t y, uint8_t Str); void Lcd1602a_Disp_Strs(uint8_t x, uint8_t y, uint8_t *Str); #endif /*__BSP_LCD1602A_H*/ bsp_lcd1602a.c #include "bsp_lcd1602a.h" static void Lcd_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /*cmd_line*/ RCC_APB2PeriphClockCmd(LCD1602A_CMD_LINE_CLK, ENABLE); GPIO_InitStructure.GPIO_Mode = MODE_GPIO; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = LCD1602A_RS_PIN; /*RS*/ GPIO_Init(LCD1602A_RS_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_RW_PIN; /*RW*/ GPIO_Init(LCD1602A_RS_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_E_PIN; /*E*/ GPIO_Init(LCD1602A_E_PORT, &GPIO_InitStructure); /*data_line*/ RCC_APB2PeriphClockCmd(LCD1602A_DATA_LINE_CLK, ENABLE); GPIO_InitStructure.GPIO_Mode = MODE_GPIO; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = LCD1602A_D0_PIN; /*D0*/ GPIO_Init(LCD1602A_D0_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_D1_PIN; /*D1*/ GPIO_Init(LCD1602A_D1_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_D2_PIN; /*D2*/ GPIO_Init(LCD1602A_D2_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_D3_PIN; /*D3*/ GPIO_Init(LCD1602A_D3_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_D4_PIN; /*D4*/ GPIO_Init(LCD1602A_D4_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_D5_PIN; /*D5*/ GPIO_Init(LCD1602A_D5_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_D6_PIN; /*D6*/ GPIO_Init(LCD1602A_D6_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = LCD1602A_D7_PIN; /*D7*/ GPIO_Init(LCD1602A_D7_PORT, &GPIO_InitStructure); } void BSP_GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, SelectStatus BitVal) { /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); assert_param(IS_GPIO_BIT_ACTION(BitVal)); if (BitVal != Bit_RESET) { GPIOx->BSRR = GPIO_Pin; } else { GPIOx->BRR = GPIO_Pin; } } void BSP_GPIO_Write(uint8_t Data) { /*D0*/ if(((Data&0x01)>>0) == 0x01) { LCD1602A_D0_PORT->BSRR = LCD1602A_D0_PIN; } else { LCD1602A_D0_PORT->BRR = LCD1602A_D0_PIN; } /*D1*/ if(((Data&0x02)>>1) == 0x01) { LCD1602A_D1_PORT->BSRR = LCD1602A_D1_PIN; } else { LCD1602A_D1_PORT->BRR = LCD1602A_D1_PIN; } /*D2*/ if(((Data&0x04)>>2) == 0x01) { LCD1602A_D2_PORT->BSRR = LCD1602A_D2_PIN; } else { LCD1602A_D2_PORT->BRR = LCD1602A_D2_PIN; } /*D3*/ if(((Data&0x08)>>3) == 0x01) { LCD1602A_D3_PORT->BSRR = LCD1602A_D3_PIN; } else { LCD1602A_D3_PORT->BRR = LCD1602A_D3_PIN; } /*D4*/ if(((Data&0x10)>>4) == 0x01) { LCD1602A_D4_PORT->BSRR = LCD1602A_D4_PIN; } else { LCD1602A_D4_PORT->BRR = LCD1602A_D4_PIN; } /*D5*/ if(((Data&0x20)>>5) == 0x01) { LCD1602A_D5_PORT->BSRR = LCD1602A_D5_PIN; } else { LCD1602A_D5_PORT->BRR = LCD1602A_D5_PIN; } /*D6*/ if(((Data&0x40)>>6) == 0x01) { LCD1602A_D6_PORT->BSRR = LCD1602A_D6_PIN; } else { LCD1602A_D6_PORT->BRR = LCD1602A_D6_PIN; } /*D7*/ if(((Data&0x80)>>7) == 0x01) { LCD1602A_D7_PORT->BSRR = LCD1602A_D7_PIN; } else { LCD1602A_D7_PORT->BRR = LCD1602A_D7_PIN; } } void Lcd_Write_State(SelectStatus Com_or_Data, uint8_t Write_Data) { LCD1602A_E_CLR; SysTick_Delay_Ms( 1); LCD1602A_RW_CLR; BSP_GPIO_WriteBit(LCD1602A_RS_PORT, LCD1602A_RS_PIN, Com_or_Data); BSP_GPIO_Write(Write_Data); SysTick_Delay_Ms( 1);/*MIN-30ns*/ LCD1602A_E_SET; SysTick_Delay_Ms( 2);/*MIN-150ns*/ LCD1602A_E_CLR; SysTick_Delay_Ms( 3); } static void Lcd_Config(void) { SysTick_Delay_Ms( 150); Lcd_Write_State(Com, 0x38); SysTick_Delay_Ms( 3); Lcd_Write_State(Com, 0x38); SysTick_Delay_Ms( 3); Lcd_Write_State(Com, 0x38); SysTick_Delay_Ms( 3); Lcd_Write_State(Com, 0x38); SysTick_Delay_Ms( 3); Lcd_Write_State(Com, 0x08);/**显示关闭**/ SysTick_Delay_Ms( 3); Lcd_Write_State(Com, 0x01);/*清屏*/ SysTick_Delay_Ms( 3); Lcd_Write_State(Com, 0x0f);/*显示开,光标开,光标闪烁开*/ SysTick_Delay_Ms( 3); Lcd_Write_State(Com, 0x06);/*地址自增一,屏幕不移动*/ } void Lcd_Init(void) { Lcd_GPIO_Config(); Lcd_Config(); } /*清屏*/ void Lcd1602a_ClearScreen(void) { Lcd_Write_State(Com, 0x01); } /*设置光标位置*/ void Lcd1602a_Set_Cursor(uint8_t x, uint8_t y) { if (y == 0) { Lcd_Write_State(Com, 0x80 + x);//第一行 } else { Lcd_Write_State(Com, 0xC0 + x);//第二行 } } /*显示字符串,坐标(x,y),str 字符串指针*/ void Lcd1602a_Disp_Strs(uint8_t x, uint8_t y, uint8_t *Str) { if (y == 0) { Lcd_Write_State(Com, 0x80 + x); } else { Lcd_Write_State(Com, 0xC0 + x); } while(*Str != ' |