#技术资源# #申请开发板# #申请原创# 手上目前有一块N32G401F8S7-1,一共20个引脚。用这个芯片简单制作了一个空调控制面板,用到了一些常用的外设驱动。N32G401这块芯片性价比是可以的,不过由于是新出的芯片,目前很多网络上对这块芯片的资料并不多,更多的是借鉴官方的操作手册以及例程,所以,本人将自己在制作空调控制面板过程中的一些经验以及驱动代码(自己造的轮子 )分享出来,希望各位大佬能够多多指导。(N32G401F8S7-1只有20个引脚有点不够用,所以参加活动也是希望能获得一块板子,这样可以对N32G401有更多的深入应用)
首先简单概括一下配置的驱动:定时器,串口,看门狗,中断,GPIO。
配置 LCD 屏幕驱动(HT1621驱动)
配置DS18B20温度传感器(one_wire 协议,需外接上拉电阻)
配置 USART,用串口传输数据
配置按键 KEY,五个按键使用中断的方式分别控制不同功能
配置 Delay,Iwdg
芯片使用的是内置的HSI高速时钟,(没有外接晶振)
内置HSI时钟是8MHZ,有±1%的误差,可以使用PLL进行倍频,如果引脚够用建议使用外接晶振
DS18B20对时序要求比较高,需要1us分辨率的延迟,(国民技术官方的例程里有好几种延迟)
对时序要求高的外设,建议使用系统时钟进行延迟
1.配置LCD屏幕驱动(HT1621)
先看数据手册,确保地址无误,如果不确定的话可以用for循环遍历所有地址,再根据实际配置地址
数码管显示数字由于是两位地址确定一个数码管,所以写了两个数组,一个对应高位,一个对应低位
每个HT1621的对应的地址都不一样,务必根据自己实际地址配置,不然显示肯定出错
以下是代码,ht1621和背光引脚的引脚初始化,需要注意的是:我用N32G401的内部8MHZ晶振HSI,然后通过PLL倍频将芯片时钟设定为64MHZ 所以定时器的预分频值为640-1。 我给背光引脚配置了一个高级定时器,配置PWM模式来控制亮度 - /**
- * [url=home.php?mod=space&uid=139335]@name[/url] LCD_BLK_Value
- * [url=home.php?mod=space&uid=42490]@function[/url] LCD背光值(0~100)
- * @param u8 set
- * [url=home.php?mod=space&uid=266161]@return[/url] none
- */
- void LCD_BLK_Value(u8 set)
- {
- TIM_Compare2_Set(TIM1, set);
- }
以下是HT1621以及背光的GPIO配置。
- /**
- * @description: 屏幕初始化
- * @param none
- * [url=home.php?mod=space&uid=266161]@return[/url] none
- */
- void LCD_Init(void)
- {
- RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
- RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
- GPIO_InitType GPIO_InitStructure;
- GPIO_Structure_Initialize(&GPIO_InitStructure);
- GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_7;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
- GPIO_Structure_Initialize(&GPIO_InitStructure);
- GPIO_InitStructure.Pin = GPIO_PIN_1;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- GPIO_Peripheral_Initialize(GPIOB, &GPIO_InitStructure);
- LCD_CS_1();
- LCD_DATA_1();
- LCD_WR_1();
- HT1621_WriteCommand(HT1621_SYS_EN); // 打开系统振荡器
- HT1621_WriteCommand(HT1621_BIAS); // BIAS 1/3 4个公共口
- HT1621_WriteCommand(HT1621_RC256); // 使用RC_256K系统时钟源,片内RC振荡器
- HT1621_WriteCommand(HT1621_WDT_DIS);
- HT1621_WriteCommand(HT1621_LCD_ON);
- LCD_BLK_Init();
- LCD_BLK_Value(LCD_BLK_VALUE); // 开启背光
- HT1621_Set_LCD(1); // 屏幕显示
- }
- /**
- * [url=home.php?mod=space&uid=139335]@name[/url] LCD_BLK_Init
- * [url=home.php?mod=space&uid=42490]@function[/url] LCD背光初始化
- * @param none
- * [url=home.php?mod=space&uid=266161]@return[/url] none
- */
- void LCD_BLK_Init(void)
- {
- RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
- RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_TIM1);
- RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
- GPIO_InitType GPIO_InitStructure;
- GPIO_Structure_Initialize(&GPIO_InitStructure);
- GPIO_InitStructure.Pin = GPIO_PIN_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
- GPIO_InitStructure.GPIO_Current = GPIO_DS_2MA;
- GPIO_InitStructure.GPIO_Alternate = GPIO_AF3_TIM1;
- GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
- TIM_TimeBaseInitType TIM_TimeBaseInitStructure;
- TIM_Base_Struct_Initialize(&TIM_TimeBaseInitStructure);
- TIM_TimeBaseInitStructure.Period = 100 - 1;
- TIM_TimeBaseInitStructure.Prescaler = 640 - 1;
- TIM_TimeBaseInitStructure.RepetCnt = 0;
- TIM_TimeBaseInitStructure.CntMode = TIM_CNT_MODE_UP;
- TIM_TimeBaseInitStructure.ClkDiv = TIM_CLK_DIV1;
- TIM_Base_Initialize(TIM1, &TIM_TimeBaseInitStructure);
- TIM_On(TIM1);
- OCInitType TIM_OCInitStructure;
- TIM_Output_Channel_Struct_Initialize(&TIM_OCInitStructure);
- TIM_OCInitStructure.OcMode = TIM_OCMODE_PWM1;
- TIM_OCInitStructure.OcNPolarity = TIM_OCN_POLARITY_LOW;
- TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
- TIM_OCInitStructure.Pulse = 0;
- TIM_OCInitStructure.OcNIdleState = TIM_OCN_IDLE_STATE_SET;
- TIM_Output_Channel2_Initialize(TIM1, &TIM_OCInitStructure);
- TIM_PWM_Output_Enable(TIM1);
- }
2.配置DS18B20温度传感器(one_wire 协议,需外接上拉电阻)
需要了解并掌握DS18B20传输时序,由于对时序要求比较高,务必确保延迟函数的准确度
以下是配置代码: - /**
- * @description: 初始化DS18B20的IO口 DQ 同时检测DS的存在
- * @param none
- * @return 返回1:不存在
- * @return 返回0:存在
- */
- u8 DS18B20_Init(void)
- {
- RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
- GPIO_InitType GPIO_InitStructure;
- GPIO_InitStructure.Pin = DS18B20_PIN; // 推挽输出
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- GPIO_Peripheral_Initialize(DS18B20_PORT, &GPIO_InitStructure);
- GPIO_Pins_Set(DS18B20_PORT, DS18B20_PIN); // 拉高
- DS18B20_Rst();
- return DS18B20_Check();
- }
- /**
- * @description: IO口输出初始化
- * @param none
- * @return none
- */
- void DS18B20_IO_OUT(void)
- {
- GPIO_InitType GPIO_InitStructure;
- GPIO_InitStructure.Pin = DS18B20_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- GPIO_Peripheral_Initialize(DS18B20_PORT, &GPIO_InitStructure);
- }
- /**
- * @description: IO口输入初始化
- * @param none
- * @return none
- */
- void DS18B20_IO_IN(void)
- {
- GPIO_InitType GPIO_InitStructure;
- GPIO_InitStructure.Pin = DS18B20_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
- GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
- GPIO_Peripheral_Initialize(DS18B20_PORT, &GPIO_InitStructure);
- }
在配置的过程中,我发现使用STM32大多都是通过bit-band操作寄存器,我查了官方的例程,也有相关例程,由于篇幅有限,就不再这里拓展,以后有机会单开一篇来讲讲 DS18B20用的是one-wire通讯协议,所以可以像这样配置操作总线传输数据: - #define DS18B20_DQ_IN GPIO_Input_Pin_Data_Get(DS18B20_PORT, DS18B20_PIN)
- #define DS18B20_DQ_OUT_1 GPIO_Pins_Set(DS18B20_PORT, DS18B20_PIN)
- #define DS18B20_DQ_OUT_0 GPIO_Pins_Reset(DS18B20_PORT, DS18B20_PIN)
3.配置按键 KEY,五个按键使用中断的方式分别控制不同功能
- /**
- * [url=home.php?mod=space&uid=139335]@name[/url] KEY_init
- * [url=home.php?mod=space&uid=42490]@function[/url] 初始化按键,启用中断
- * @param none
- * @return none
- */
- void KEY_init(void)
- {
- RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA); // 按键全部使用GPIOA
- RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
- RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_TIM6);
- GPIO_InitType GPIO_InitStructure;
- GPIO_Structure_Initialize(&GPIO_InitStructure);
- GPIO_InitStructure.Pin = KEY6_GPIO_PIN | KEY7_GPIO_PIN | KEY8_GPIO_PIN | KEY9_GPIO_PIN | KEY10_GPIO_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT; // 输入
- GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
- GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
- GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE5, AFIO_EXTI_PA0);
- GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE6, AFIO_EXTI_PA1);
- GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE7, AFIO_EXTI_PA2);
- GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE8, AFIO_EXTI_PA3);
- GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE9, AFIO_EXTI_PA4);
- /* Configure key EXTI line */
- EXTI_InitType EXTI_InitStructure;
- EXTI_InitStructure.EXTI_Line = EXTI_LINE5;
- EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
- EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
- EXTI_InitStructure.EXTI_LineCmd = ENABLE;
- EXTI_Peripheral_Initializes(&EXTI_InitStructure);
- EXTI_InitStructure.EXTI_Line = EXTI_LINE6;
- EXTI_Peripheral_Initializes(&EXTI_InitStructure);
- EXTI_InitStructure.EXTI_Line = EXTI_LINE7;
- EXTI_Peripheral_Initializes(&EXTI_InitStructure);
- EXTI_InitStructure.EXTI_Line = EXTI_LINE8;
- EXTI_Peripheral_Initializes(&EXTI_InitStructure);
- EXTI_InitStructure.EXTI_Line = EXTI_LINE9;
- EXTI_Peripheral_Initializes(&EXTI_InitStructure);
- /* Set key input interrupt priority */
- NVIC_InitType NVIC_InitStructure;
- NVIC_Priority_Group_Set(NVIC_PER3_SUB1_PRIORITYGROUP);
- NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_SUB_PRIORITY_3;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PER_PRIORITY_3;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Initializes(&NVIC_InitStructure);
- }
4.配置USART,IWDG,DELAY 以下是官方例程中给的两种中断方式,根据实际需求选择使用 配置USART:
- /**
- * @name USART2_Init
- * @function USART2初始化 逻辑"0"发送 逻辑"1"接收
- * @param none
- * @return none
- */
- void USART2_Init(void)
- {
- RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_USART2);
- RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOD);
- RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
- GPIO_InitType GPIO_InitStructure;
- /* 配置USARTy Tx为复用推挽输出 */
- GPIO_InitStructure.Pin = GPIO_PIN_15;
- GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
- GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_USART2;
- GPIO_Peripheral_Initialize(GPIOD, &GPIO_InitStructure);
- /* 配置USARTy Rx为复用推挽输入和上拉输入 */
- GPIO_InitStructure.Pin = GPIO_PIN_14;
- GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_USART2;
- GPIO_Peripheral_Initialize(GPIOD, &GPIO_InitStructure);
- USART_InitType USART2_InitStructure;
- USART2_InitStructure.BaudRate = 9600;
- USART2_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
- USART2_InitStructure.WordLength = USART_WL_8B;
- USART2_InitStructure.Parity = USART_PE_NO;
- USART2_InitStructure.StopBits = USART_STPB_1;
- USART2_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
- USART_Initializes(USART2, &USART2_InitStructure);
- NVIC_InitType NVIC_InitStructure;
- NVIC_Priority_Group_Set(NVIC_PER2_SUB2_PRIORITYGROUP);
- NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Initializes(&NVIC_InitStructure);
- USART_Interrput_Enable(USART2, USART_INT_RXDNE);
- USART_Interrput_Enable(USART2, USART_INT_TXDE);
- USART_Enable(USART2);
- }
配置IWDG:
- __IO uint32_t LsiFreq = 40000; // 内部低速时钟频率,初始值设定为 40000
- void IWDG_Config(IWDG_CONFIG_PRESCALER IWDG_prescaler, uint16_t reload_value)
- {
- /* 由于 LSI 频率变化,超时时间可能有所不同 */
- /* 关闭 IWDG_PREDIV 和 IWDG_RELV 寄存器的写保护 */
- IWDG_Write_Protection_Disable();
- /* IWDG 计数器时钟预分频设置 */
- IWDG_Prescaler_Division_Set(IWDG_prescaler);
- /* 设置 IWDG 重装载值 */
- /* 设置计数器重装载值以获取 x 秒的 IWDG 超时。
- 计数器重装载值时间 = x(秒) / IWDG 计数器时钟周期
- = x(秒) / (LSI/IWDG_prescaler)
- */
- IWDG_Counter_Reload(reload_value);
- /* 使用 IWDG_PREDIV 的值重新加载计数器到 IWDG_RELV 寄存器,以防止复位 */
- IWDG_Key_Reload();
- /* 启用 IWDG(LSI 振荡器将由硬件启用) */
- IWDG_Enable();
- }
- void IWDG_Feed(void)
- {
- /* 将重装载寄存器的值写入计数器 */
- IWDG_Key_Reload();
- }
本文由于篇幅原因仅分享所有的驱动配置,各个硬件外设通讯协议以及时序都能在网上找到资源,只需要将驱动配置完成即可使用。 欢迎官方以及各位工程师帮忙指出不足之处~
|