- uint8_t poweron = 1;
- uint16_t refresh_count = 0;
- uint8_t keysoundcount = 0;
- uint16_t key_downcount = 0;
- void key_init()
- {
- GPIO_InitTypeDef gpiodef;
- gpiodef.Pins = GPIO_PIN_2;
- gpiodef.Mode = GPIO_MODE_INPUT_PULLDOWN;
- gpiodef.IT = GPIO_IT_NONE;
- GPIO_Init(CW_GPIOB,&gpiodef);
- }
定时器初始化,开启溢出中断,实现一个1ms的定时器
- void gtimer1_init()
- {
- GTIM_InitTypeDef GTIM_InitStruct = {0};
- __RCC_GTIM1_CLK_ENABLE();
- GTIM_InitStruct.Mode = GTIM_MODE_TIME;
- GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV64;
- GTIM_InitStruct.ReloadValue = 1000-1;
- GTIM_TimeBaseInit(CW_GTIM1, >IM_InitStruct);
- GTIM_ITConfig(CW_GTIM1, GTIM_IT_OV, ENABLE);
- NVIC_EnableIRQ(GTIM1_IRQn);
- GTIM_Cmd(CW_GTIM1, ENABLE);
- }
在定时器中断中实现按键检测、定时刷新数据和串口空闲判断等功能,默认每5秒刷新一次二氧化碳和温湿度数据,检测到单击动作后立即刷新
- void poweronoff()
- {
- if(poweron == 0)
- {
- poweron = 1;
- }
- else
- {
- poweron = 3;
- }
- }
- void GTIM1_IRQHandler(void)
- {
- if (GTIM_GetITStatus(CW_GTIM1, GTIM_IT_OV))
- {
- GTIM_ClearITPendingBit(CW_GTIM1, GTIM_IT_OV);
- if(uart_rxtime_count > 0)
- {
- uart_rxtime_count -= 1;
- if(uart_rxtime_count == 0)
- show_co2();
- }
- if(keysoundcount > 0)
- {
- keysoundcount -= 1;
- if(keysoundcount == 0)
- {
- yuyy_keybeep(0);
- }
- }
- if(refresh_count > 0)
- refresh_count -= 1;
- else
- {
- refresh_data();
- refresh_count = 4999;
- }
- if(GPIO_ReadPin(CW_GPIOB,GPIO_PIN_2)==GPIO_Pin_SET)
- {
- if(key_downcount < 0xFFFF)
- key_downcount += 1;
- if(key_downcount == 2000)
- {
- poweronoff();
- }
- }
- else
- {
- if(poweron == 2 && key_downcount > 10 && key_downcount < 1000)
- {
- refresh_count = 0;
- yuyy_keybeep(1);
- keysoundcount = 100;
- }
- key_downcount = 0;
- }
- }
- }
LCD12864初始化
LCD12864使用SPI进行通讯,5个IO都是输出模式
cs rst a0使用软件控制,sck mosi复用为SPI,这里只有mcu到lcd的单向通讯所以SPI配制成只发送模式就行了
- YUYY_HS12864G18B_DEV_t hs12864_dev;
- void hs12864g18b_init(void)
- {
- GPIO_InitTypeDef gpiodef;
- hs12864_dev.cs.gpio = CW_GPIOA;
- hs12864_dev.cs.pin = GPIO_PIN_4;
- hs12864_dev.rst.gpio = CW_GPIOA;
- hs12864_dev.rst.pin = GPIO_PIN_3;
- hs12864_dev.a0.gpio = CW_GPIOA;
- hs12864_dev.a0.pin = GPIO_PIN_2;
- hs12864_dev.sck.gpio = CW_GPIOA;
- hs12864_dev.sck.pin = GPIO_PIN_5;
- hs12864_dev.mo.gpio = CW_GPIOA;
- hs12864_dev.mo.pin = GPIO_PIN_7;
-
- RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOA, ENABLE);
- gpiodef.Pins = GPIO_PIN_5|GPIO_PIN_7|GPIO_PIN_4|GPIO_PIN_3|GPIO_PIN_2;
- gpiodef.Mode = GPIO_MODE_OUTPUT_PP;
- gpiodef.IT = GPIO_IT_NONE;
- gpiodef.Speed = GPIO_SPEED_HIGH;
- GPIO_Init(CW_GPIOA,&gpiodef);
-
- RCC_APBPeriphClk_Enable2(RCC_APB2_PERIPH_SPI1, ENABLE);
- PA05_AFx_SPI1SCK();
- PA07_AFx_SPI1MOSI();
- SPI_InitTypeDef spidef;
- spidef.SPI_Direction = SPI_Direction_1Line_TxOnly;
- spidef.SPI_Mode = SPI_Mode_Master;
- spidef.SPI_DataSize = SPI_DataSize_8b;
- spidef.SPI_CPOL = SPI_CPOL_High;
- spidef.SPI_CPHA = SPI_CPHA_2Edge;
- spidef.SPI_NSS = SPI_NSS_Soft;
- spidef.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
- spidef.SPI_FirstBit = SPI_FirstBit_MSB;
- spidef.SPI_Speed = SPI_Speed_High;
- SPI_Init(CW_SPI1,&spidef);
- SPI_Cmd(CW_SPI1, ENABLE);
-
- hs12864_dev.spix = CW_SPI1;
- yuyy_hs12864g18b_init(&hs12864_dev);
- yuyy_hs12864g18b_clear_screen(&hs12864_dev);
- }
DHTC12初始化
DHTC12使用I2C通讯,DHTC12最高支持100K的通讯速率,注意SCL和SDA要接上拉电阻
根据当先系统时钟调整I2C速率,CW32的硬件I2C通讯代码可以参考这篇https://bbs.21ic.com/icview-3306992-1-1.html
- YUYY_DHTC12_DEV_t dhtc12_dev;
- YUYY_IIC_DEV_t iic_dev;
- void dhtc12_init()
- {
- I2C_InitTypeDef I2C_InitStruct;
- GPIO_InitTypeDef GPIO_InitStructure;
- __RCC_GPIOB_CLK_ENABLE();
- PB10_AFx_I2C1SCL();
- PB11_AFx_I2C1SDA();
-
- GPIO_InitStructure.Pins = GPIO_PIN_10|GPIO_PIN_11;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_OD; //
- GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
- GPIO_Init(CW_GPIOB, &GPIO_InitStructure);
-
- __RCC_I2C1_CLK_ENABLE();
- I2C_InitStruct.I2C_BaudEn = ENABLE;
- I2C_InitStruct.I2C_Baud = 79; //100K=(64000000/(8*(1+79))
- I2C_InitStruct.I2C_FLT = ENABLE;
- I2C_InitStruct.I2C_AA = DISABLE;
- I2C1_DeInit();
- I2C_Master_Init(CW_I2C1,&I2C_InitStruct);//初始化模块
- I2C_Cmd(CW_I2C1,ENABLE); //模块使能
-
- iic_dev.iictype = YUYY_IIC_TYPE_HARD;
- iic_dev.hiicx = CW_I2C1;
- dhtc12_dev.iicx = &iic_dev;
- yuyy_dhtc12_init(&dhtc12_dev);
- }
串口初始化
S8的数据通讯格式如图
S8的串口波特率是9600,初始化串口3并开启中断,
- #define UART_BUFFER_LEN 10
- uint8_t uart_rxbuffer[UART_BUFFER_LEN] = {0};
- uint8_t readco2_cmd[] = { 0xFE, 0x04, 0x00, 0x03, 0x00, 0x01, 0xD5, 0xC5};
- uint8_t uart_rxlen = 0;
- uint8_t uart_rxtime_count = 0;
- uint8_t uart_txlen = 0;
- uint8_t uart_txindex = 0;
- void uart_init(void)
- {
- //UYSART3 TX PA9 RX PA10
- RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_GPIOA,ENABLE);
- RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_UART3, ENABLE);
-
- GPIO_InitTypeDef GPIO_InitStructure;
- //UART TX RX 复用
- PA09_AFx_UART3TXD();
- PA10_AFx_UART3RXD();
- GPIO_InitStructure.Pins = GPIO_PIN_9;
- GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
- GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.Pins = GPIO_PIN_10;
- GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
- GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
-
- USART_InitTypeDef USART_InitStructure;
- USART_InitStructure.USART_BaudRate = 9600;
- USART_InitStructure.USART_Over = USART_Over_16;
- USART_InitStructure.USART_Source = USART_Source_PCLK;
- USART_InitStructure.USART_UclkFreq = 64000000;
- USART_InitStructure.USART_StartBit = USART_StartBit_FE;
- 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(CW_UART3, &USART_InitStructure);
-
- //优先级,无优先级分组
- NVIC_SetPriority(UART3_IRQn, 0);
- //UARTx中断使能
- NVIC_EnableIRQ(UART3_IRQn);
-
- USART_ITConfig(CW_UART3, USART_IT_RC, ENABLE);
- }
在串口中断函数中处理接收和发送数据,每次接收数据重置接收时间计数,当在定时中断中计数减为0时判断为数据已接收完成,进入数据显示方法
- void UART3_IRQHandler(void)
- {
- if(USART_GetITStatus(CW_UART3, USART_IT_RC) != RESET)
- {
- uart_rxtime_count = 5;
- uart_rxbuffer[uart_rxlen++] = USART_ReceiveData_8bit(CW_UART3);
- USART_ClearITPendingBit(CW_UART3, USART_IT_RC);
- }
- if(USART_GetITStatus(CW_UART3, USART_IT_TXE) != RESET)
- {
- if(uart_txlen > 0)
- {
- USART_SendData_8bit(CW_UART3, readco2_cmd[uart_txindex++]);
- uart_txlen--;
- }
- else
- {
- USART_ITConfig(CW_UART3, USART_IT_TXE, DISABLE);
- }
- USART_ClearITPendingBit(CW_UART3, USART_IT_TXE);
- }
- }
S8的查询命令,开启发送空中断开始发送查询命令
- void uart_read_co2cmd()
- {
- uart_txlen = 8;
- uart_txindex = 0;
- uart_rxlen = 0;
- USART_ITConfig(CW_UART3, USART_IT_TXE, ENABLE);
- }
二氧化碳浓度数据的展示方法
- void show_co2()
- {
- uint16_t co2ppm = 0;
- char out[20];
- uint8_t outlen;
- if(uart_rxlen > 0 && uart_rxbuffer[0] == 0xFE && uart_rxbuffer[1] == 0x04 && uart_rxbuffer[2] == 0x02)
- {
- co2ppm = (uart_rxbuffer[3]<<8)+uart_rxbuffer[4];
- outlen = sprintf(out,"CO2 %d ppm",co2ppm);
- yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,2,0,(uint8_t *)out);
- yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,2,8*outlen,(uint8_t *)" ");
- }
- }
蜂鸣器功能
这里使用的是无源蜂鸣器,与有源蜂鸣器不同内部没有振荡源,需要输出波形才能发声,通过改变输出波形的频率可以让蜂鸣器发出不同的声调
PB09是Gtimer4的输出io
初始化GTimer4输出PWM
- void beeppwminit()
- {
- GTIM_InitTypeDef GTIM_InitStruct = {0};
- GPIO_InitTypeDef gpiodef;
- __RCC_GPIOC_CLK_ENABLE();
- gpiodef.Pins = GPIO_PIN_9;
- gpiodef.IT = GPIO_IT_NONE;
- gpiodef.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_Init(CW_GPIOB,&gpiodef);
- PB09_AFx_GTIM4CH1();
-
- __RCC_GTIM4_CLK_ENABLE();
- GTIM_InitStruct.Mode = GTIM_MODE_TIME;
- GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV32;
- GTIM_InitStruct.ReloadValue = 1000-1;
- GTIM_TimeBaseInit(CW_GTIM4, >IM_InitStruct);
- GTIM_OCInit(CW_GTIM4, GTIM_CHANNEL1, GTIM_OC_OUTPUT_PWM_HIGH);
- GTIM_SetCompare1(CW_GTIM4, 0);
- GTIM_Cmd(CW_GTIM4, ENABLE);
- }
利用无源蜂鸣器实现播放开关机音乐和按键声音,通过改变输出的PWM频率就能改变蜂鸣器音调从而实现开关机音乐的播放
- //定义低音音名 (单位:HZ)
- #define L1 262
- #define L2 294
- #define L3 330
- #define L4 349
- #define L5 392
- #define L6 440
- #define L7 494
- //定义中音音名
- #define M1 523
- #define M2 587
- #define M3 659
- #define M4 698
- #define M5 784
- #define M6 880
- #define M7 988
- //定义高音音名
- #define H1 1047
- #define H2 1175
- #define H3 1319
- #define H4 1397
- #define H5 1568
- #define H6 1760
- #define H7 1976
- //定义时值单位,决定演奏速度(数值单位:ms)
- #define T 2000
- typedef struct
- {
- short mName;//音名:取值L1~L7、M1~M7、H1~H7分别表示低音、中音、高音的1234567,取0表示休止符
- short mTime;//时值:取值T、T/2、T/4、T/8、T/16、T/32分别表示全音符、二分音符、四音符、八音符...取0表示演奏结束
- }music_data_t;
- const music_data_t powerupbeepdata[]={
- {M3,T/8},{M3,T/8},{M3,T/8},{M1,T/16},{M3,T/16},{0,T/16},{M5,T/8},{0,T/16},{L5,T/8},
- {0,0}
- };
- const music_data_t powerdownbeepdata[]={
- {L5,T/8},{M4,T/8},{0,T/16},{M4,T/8},{M4,T/8},{M3,T/8},{M2,T/8},{M1,T/8},
- {0,0}
- };
- void sound(uint16_t hz)
- {
- if(hz == 0)
- return;
- uint32_t p = 2000000/hz;
- GTIM_SetReloadValue(CW_GTIM4,p-1);
- GTIM_SetCompare1(CW_GTIM4,p/2);
- }
- void beep_music(music_data_t *md)
- {
- uint8_t i=0;
- while(md[i].mTime > 0)
- {
- sound(md[i].mName);
- yuyy_delay_ms(md[i].mTime);
- GTIM_SetCompare1(CW_GTIM4,0);
- yuyy_delay_ms(15);
- i++;
- }
- GTIM_SetCompare1(CW_GTIM4,0);
- }
- void yuyy_powerupbeep()
- {
- beep_music(powerupbeepdata);
- }
- void yuyy_powerdownupbeep()
- {
- beep_music(powerdownbeepdata);
- }
- void yuyy_keybeep(uint8_t on)
- {
- if(on == 0)
- {
- GTIM_SetCompare1(CW_GTIM4,0);
- }
- else
- {
- sound(M3);
- }
- }
主函数中调用初始化方法,在主循环中实现开关机画面
- int32_t main(void)
- {
- RCC_HSE_8M_PLL64M_init();
- __RCC_GPIOA_CLK_ENABLE();
- __RCC_GPIOB_CLK_ENABLE();
- __RCC_GPIOC_CLK_ENABLE();
-
- key_init();
- uart_init();
- gtimer1_init();
- beeppwminit();
- dhtc12_init();
- hs12864g18b_init();
- GPIO_InitTypeDef gpiodef;
- gpiodef.Pins = GPIO_PIN_2;
- gpiodef.IT = GPIO_IT_NONE;
- gpiodef.Speed = GPIO_SPEED_HIGH;
- gpiodef.Mode = GPIO_MODE_OUTPUT_PP;
- gpiodef.Pins = GPIO_PIN_13;
- GPIO_Init(CW_GPIOC,&gpiodef);
- GPIO_WritePin(CW_GPIOC,GPIO_PIN_13,GPIO_Pin_SET);
- while(1)
- {
- if(poweron == 1)
- {
- yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,0,0,(uint8_t *)" CO2 Detector");
- yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,2,0,(uint8_t *)" CW32 Inside");
- yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,0,(uint8_t *)"Code by yuyy1989");
- yuyy_powerupbeep();
- poweron = 2;
- refresh_count = 0;
- }
- else if(poweron == 3)
- {
- yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,2,0,(uint8_t *)" CW32 Inside");
- yuyy_hs12864g18b_display_string_8x16(&hs12864_dev,0,4,0,(uint8_t *)"Code by yuyy1989");
- yuyy_powerdownupbeep();
- yuyy_hs12864g18b_clear_screen(&hs12864_dev);
- GPIO_WritePin(CW_GPIOC,GPIO_PIN_13,GPIO_Pin_SET);
- poweron = 0;
- }
- if(poweron > 0)
- {
- yuyy_delay_ms(500);
- GPIO_TogglePin(CW_GPIOC,GPIO_PIN_13);
- }
- else
- {
- yuyy_delay_ms(10);
- }
- }
- }
最终效果