- #include "ac780x_gpio.h"
- #define LED1PORT GPIOA
- #define LED1PIN GPIO_PIN2
- #define LED2PORT GPIOA
- #define LED2PIN GPIO_PIN3
- #define KEYPORT GPIOA
- #define KEYPIN GPIO_PIN11
- void test_setled1onoff(uint8_t on)
- {
- if(on)
- GPIO_SetPinLevel(LED1PORT, LED1PIN, GPIO_LEVEL_HIGH);
- else
- GPIO_SetPinLevel(LED1PORT, LED1PIN, GPIO_LEVEL_LOW);
- }
- uint8_t test_getled1state(void)
- {
- if(GPIO_GetPinLevel(LED1PORT, LED1PIN) == GPIO_LEVEL_HIGH)
- return 1;
- return 0;
- }
- void test_setled2onoff(uint8_t on)
- {
- if(on)
- GPIO_SetPinLevel(LED2PORT, LED2PIN, GPIO_LEVEL_HIGH);
- else
- GPIO_SetPinLevel(LED2PORT, LED2PIN, GPIO_LEVEL_LOW);
- }
- uint8_t test_getled2state(void)
- {
- if(GPIO_GetPinLevel(LED2PORT, LED2PIN) == GPIO_LEVEL_HIGH)
- return 1;
- return 0;
- }
- void test_ledinit(void)
- {
- GPIO_SetFunc(LED1PORT, LED1PIN, GPIO_FUN0);/*功能复用选择.*/
- GPIO_SetFunc(LED2PORT, LED2PIN, GPIO_FUN0);
- /*设置LED引脚为GPIO输出.*/
- GPIO_SetDir(LED1PORT, LED1PIN, GPIO_OUT);
- GPIO_SetDir(LED2PORT, LED2PIN, GPIO_OUT);
- }
- void test_keyinit(void)
- {
- GPIO_SetFunc(KEYPORT, KEYPIN, GPIO_FUN0); /*功能复用选择.*/
- /*设置按键引脚为输入,检测按键动作.*/
- GPIO_SetDir(KEYPORT, KEYPIN, GPIO_IN); /*设置为输入模式.*/
- }
- void test_prockey(void)
- {
- if(GPIO_GetPinLevel(KEYPORT, KEYPIN) == GPIO_LEVEL_LOW)
- {
- mdelay(30);
- if(GPIO_GetPinLevel(KEYPORT, KEYPIN) == GPIO_LEVEL_LOW)
- {
- while(GPIO_GetPinLevel(KEYPORT, KEYPIN) == GPIO_LEVEL_LOW);
- test_setled1onoff(!test_getled1state());
- test_setled2onoff(!test_getled2state());
- }
- }
- }
- int main(void)
- {
- InitDelay();
- test_ledinit();
- test_keyinit();
- test_setled1onoff(1);
- test_setled2onoff(0);
- while (1)
- {
- test_prockey();
- }
- }
编译烧录,烧录前注意选择自己使用的烧录器,建议勾选上Reset and run选项
运行效果
3.2 UART串口通信
这个板子自带了USB转串口,通过Type-C数据线连接时,会出现一个串口设备
打开例程02_UART_Interrupt,查看串口配置
查看原理图可以看到所用IO和板载的USB转串口使用的IO一致
编译烧录,打开串口助手,配置好参数,发送字符串会返回和发送相同的字符串
下面把串口通讯代码合并到点灯的程序里,实现串口命令控制点灯
在串口空闲中断里添加代码
- if(g_rxBuf[0] == 'L' && g_rxBuf[1] == 'E' && g_rxBuf[2] == 'D')
- {
- if(g_rxBuf[3] == '1')
- {
- if(g_rxBuf[4] == '0')
- {
- test_setled1onoff(0);
- }
- else if(g_rxBuf[4] == '1')
- {
- test_setled1onoff(1);
- }
- }
- else if(g_rxBuf[3] == '2')
- {
- if(g_rxBuf[4] == '0')
- {
- test_setled2onoff(0);
- }
- else if(g_rxBuf[4] == '1')
- {
- test_setled2onoff(1);
- }
- }
- }
运行效果
3.3 PWM实现呼吸灯
开发板上的2个LED可以用PWM驱动,基于例程里的PWM示例,做一个两个灯珠交替呼吸的程序
- #include "ac780x_gpio.h"
- #include "ac780x_pwm.h"
- #include "ac780x_pwm_reg.h"
- void test_pwm_Init(void)
- {
- PWM_ConfigType config;
- PWM_ModulationConfigType pwmConfig;
- PWM_IndependentChConfig independentChConfig[2];
- memset(&config, 0U, sizeof(config));
- memset(&pwmConfig, 0U, sizeof(pwmConfig));
- memset(&independentChConfig, 0U, sizeof(independentChConfig));
- GPIO_SetFunc(GPIOA, GPIO_PIN2, GPIO_FUN1); /* PA2--PWM2_CH1.*/
- GPIO_SetFunc(GPIOA, GPIO_PIN3, GPIO_FUN1); /* PA3--PWM2_CH0.*/
- /*
- 边沿对齐PWM模式:
- 周期=(MCVR-CNTIN+1)*PWM计数器时钟周期
- 脉宽=(CHnV-CNTIN+1)*PWM计数器时钟周期
- 中心对齐PWM模式:
- 周期=2*(MCVR-CNTIN)*PWM计数器时钟周期
- 脉宽=2*(CHnV-CNTIN)*PWM计数器时钟周期
- */
- independentChConfig[0].channel = PWM_CH_0; /*独立输出通道选择 */
- independentChConfig[0].chValue = 0; /*通道channel值,决定占空比 */
- independentChConfig[0].levelMode = PWM_HIGH_TRUE; /*输出PWM高有效,可配置高有效或低有效 */
- independentChConfig[0].polarity = PWM_OUTPUT_POLARITY_ACTIVE_HIGH; /*通道输出极性配置为高有效,PWM Mask后输出为低电平 */
- independentChConfig[0].interruptEn = ENABLE; /*通道匹配中断使能位 */
- independentChConfig[0].initLevel = PWM_LOW_LEVEL; /*通道初始电平输出配置,该配置受initChOutputEn控制,决定PMM计数器未工作前PWM口的输出电平 */
- independentChConfig[0].triggerEn = DISABLE; /*通道匹配触发使能位,在通道值匹配时可产生触发信号用于其他模块的触发信号 */
- independentChConfig[1].channel = PWM_CH_1; /*独立输出通道选择 */
- independentChConfig[1].chValue = 0; /*通道channel值,决定占空比 */
- independentChConfig[1].levelMode = PWM_HIGH_TRUE; /*输出PWM高有效,可配置高有效或低有效 */
- independentChConfig[1].polarity = PWM_OUTPUT_POLARITY_ACTIVE_HIGH; /*通道输出极性配置为高有效,PWM Mask后输出为低电平 */
- independentChConfig[1].interruptEn = ENABLE; /*通道匹配中断使能位 */
- independentChConfig[1].initLevel = PWM_LOW_LEVEL; /*通道初始电平输出配置,该配置受initChOutputEn控制,决定PMM计数器未工作前PWM口的输出电平 */
- independentChConfig[1].triggerEn = DISABLE; /*通道匹配触发使能位,在通道值匹配时可产生触发信号用于其他模块的触发信号 */
- pwmConfig.countMode = PWM_UP_DOWN_COUNT; /*PWM计数器模式,PWM_UP_COUNT--向上计数模式;PWM_UP_DOWN_COUNT-- 向上/向下计数模式 */
- pwmConfig.independentChannelNum = 2; /*独立通道数目*/
- pwmConfig.combineChannelNum = 0; /*组合通道对数 */
- pwmConfig.independentChConfig = independentChConfig; /*独立通道配置赋值 */
- pwmConfig.combineChConfig = NULL; /*组合通道配置赋值 */
- pwmConfig.deadtime = 0; /*死区时间值,死区功能仅在组合模式下有效 */
- pwmConfig.deadtimePsc = PWM_DEADTIME_DIVID_1; /*死区时间时钟分频系数,死区功能仅在组合模式下有效 */
- pwmConfig.initChOutputEn = ENABLE; /*初始化通道输出使能位,使能后独立PWM模式的 initLevel 和组合模式的ch1stInitLevel和ch2ndInitLevel配置才会生效*/
- pwmConfig.initTriggerEn = DISABLE; /*PWM初始值触发使能位 */
- /*
- 向上-向下技术模式下,频率计算为:
- freq = pwm_clk/(2*(maxValue - initValue))
- 16000/(2*8000) = 1K
- */
- config.mode = PWM_MODE_MODULATION; /*PWM模式配置,PWM_MODE_MODULATION--PWM调制模式 */
- config.initModeStruct = &pwmConfig; /*不同模式相应初始化配置结构体赋值 */
- config.clkSource = PWM_CLK_SOURCE_APB; /*PWM时钟源选择 */
- config.clkPsc = 0; /*时钟分频系数 */
- config.initValue = 0; /*初始计数值 */
- config.maxValue = 8000; /*最大计数值,决定输出波形频率 */
- config.overflowInterrupEn = ENABLE; /*溢出中断使能位 */
- config.cntOverflowFreq = 0; /*溢出中断产生的频率与计数器频率的关系,0表示每次计数器溢出都产生中断,1表示间隔一次,以此类推 */
- config.interruptEn = ENABLE; /*PWM总中断使能位 */
- //config.callBack = PWM2_Callback; /*中断回调函数 */
- PWM_Init(PWM2, &config);
- }
- int main(void)
- {
- uint16_t pwm = 0;
- uint8_t pwmup = 1;
- InitDelay();
- while (1)
- {
- mdelay(2);
- PWM_SetChannelCountValue(PWM2,0,8000 - pwm);
- PWM_SetChannelCountValue(PWM2,1,pwm);
- if(pwmup > 0)
- {
- if(pwm < 8000 - 10)
- {
- pwm += 10;
- }
- else
- {
- pwm = 8000;
- pwmup = 0;
- }
- }
- else
- {
- if(pwm > 10)
- {
- pwm -= 10;
- }
- else
- {
- pwm = 0;
- pwmup = 1;
- }
- }
-
- }
- }
运行效果
3.4 通过ADC实现使用电位器控制LED亮度
开发板上有个可调电位器,用它来实现旋转旋钮调节LED亮度
- #include "ac780x_gpio.h"
- #include "ac780x_pwm.h"
- #include "ac780x_pwm_reg.h"
- #include "ac780x_adc_reg.h"
- void test_pwm_Init(void)
- {
- //省略,参考上个例程
- }
- void test_adc_init(void)
- {
- ADC_ConfigType adcConfig; /*! ADC初始化配置*/
- memset(&adcConfig, 0x00, sizeof(adcConfig)); /*! 清空结构体*/
- /*! ADC输入端口(电位器)配置*/
- GPIO_SetFunc(GPIOA, GPIO_PIN10, GPIO_FUN2); /*! PA10复用为FUN2,为ADC_IN1 ,对应电位器VR1*/
- /*! ADC配置
- ADC固定为12位分辨率,工作模式为MODE1(工作模式内容见参考手册8.4.2章节),规则组扫描+注入组扫描模式多通道单次转换,规则组长度为3,注入组长度为0
- 每触发一次进行一次ADC转换,每次转换规则组中的3个通道。
- */
- adcConfig.clkPsc = ADC_CLK_PRESCALER_2; /*! ADC时钟分频设置,Set ADC Clk = APB时钟频率/(clkPsc + 1) = 16M/2 = 8M */
- adcConfig.scanModeEn = DISABLE; /*! 模式配置SCAN:扫描模式使能位 多通道需使能扫描模式,单通道则不需要使能*/
- adcConfig.continuousModeEn = DISABLE; /*! 模式配置CONT:连续模式使能位 0:触发一次后只转换一次,1:触发后可连续转换*/
- adcConfig.regularDiscontinuousModeEn = DISABLE; /*! 模式配置DISCEN:打开规则组间断转换模式*/
- adcConfig.injectDiscontinuousModeEn = DISABLE; /*! 模式配置IDISEN:打开注入组间断转换模式*/
- adcConfig.injectAutoModeEn = DISABLE; /*! 模式配置IAUTO:自动注入模式*/
- adcConfig.intervalModeEn = DISABLE; /*! 模式配置INTERVAL:注入组为间隔转换模式*/
- adcConfig.regularDiscontinuousNum = 0; /*! 规则组子组长度,用于Mode7和Mode8*/
- adcConfig.interruptEn = DISABLE; /*! 总中断使能*/
- adcConfig.voltageRef = ADC_VOLTAGEREF_VDDA; /*! ADC参考源选择 */
- adcConfig.regularTriggerMode = ADC_TRIGGER_INTERNAL; /*! 规则组触发源类型选择*/
- adcConfig.injectTriggerMode = ADC_TRIGGER_INTERNAL; /*! 注入组触发源类型选择*/
- adcConfig.regularSequenceLength = 3; /*! 规则组长度*/
- adcConfig.injectSequenceLength = 0; /*! 注入组长度*/
- adcConfig.dataAlign = ADC_DATA_ALIGN_RIGHT; /*! 数据右对齐*/
- adcConfig.callBack = NULL; /*! ADC回调函数*/
- adcConfig.powerMode = ADC_POWER_ON; /*! ADC上电*/
- ADC_Init(ADC0, &adcConfig); /*! ADC works Mode Config*/
- /*!
- ADC转换率计算公式:
- 总转换时间=(SPT+ 12)/ADC时钟频率+5个APB时钟周期
- 备注:
- 1.SPT为采样周期个数,具体见下面ADC_SPT_CLK_x。
- 2.ADC时钟频率 = APB时钟频率 /(分频系数+1)
- 3.7802x ADC支持的最高采样率为250Ksps(即转换时间不低于4us),如果配置采样率高于该值,可能会导致采样结果精度显著减低。
- */
- /*规则组通道转换序列和转换速率配置*/
- ADC_SetRegularGroupChannel(ADC0, ADC_CH_1, ADC_SPT_CLK_33, 0); /*! 采样&转换时间= (33+12)/8000000 + 5/16000000 ≈ 5.94us */
- /*! Bandgap或T-sensor内部通道配置*/
- ADC_SetInternalChannel(ADC0, ADC_INTERNAL_TSENSOR); /*! 内部电压信号选择(仅在使用了ADC_CH_VIN 时配置) */
- ADC_SetVBufEnableFlag(ADC0, ENABLE); /*! Bandgap和T-sensor内部通道使能(仅在使用了ADC_CH_VIN 时配置) */
- }
- uint16_t test_getadc(void)
- {
- uint16_t adcvalue = 0;
- ADC_SoftwareStartRegularConvert(ADC0); /*! 软件触发规则组采样*/
- while (!ADC_GetEOCFlag(ADC0, 0)); /*! 等待规则组最后一个通道转换完成*/
- adcvalue = ADC_GetRegularData(ADC0, 0); /*! 获取规则组0的转换值*/
- return adcvalue;
- }
- int main(void)
- {
- uint16_t pwm = 0;
- InitDelay();
- test_adc_init();
- test_pwm_Init();
- while (1)
- {
- mdelay(10);
- pwm = test_getadc()*8000/4095;
- PWM_SetChannelCountValue(PWM2,0,8000 - pwm);
- PWM_SetChannelCountValue(PWM2,1,pwm);
- }
- }
运行效果
3.5 定时器测试
用定时器实现两个LED交替闪烁
- #include "ac780x_gpio.h"
- #include "ac780x_timer.h"
- #define Timer_CLK (APB_BUS_FREQ) /*!定时器时钟为APB时钟 */
- #define TimeoutS(n) (Timer_CLK*n - 1) /*!n 秒超时值 */
- #define Timeout1ms (Timer_CLK/1000-1) /*!1ms超时值 */
- #define Timeout500ms (Timer_CLK/2-1) /*!500ms超时值 */
- //LED相关函数省略
- void test_timer_cb(void *device, uint32_t wpara, uint32_t lpara)
- {
- test_setled1onoff(!test_getled1state());
- test_setled2onoff(!test_getled2state());
- }
- void test_timer_init()
- {
- TIMER_ConfigType timerConfig;
- memset(&timerConfig, 0, sizeof(timerConfig));
- /*!配置定时器.*/
- timerConfig.periodValue = Timeout500ms; /*! 定义超时值为500ms */
- timerConfig.linkModeEn = DISABLE; /*! 禁能链接模式 */
- timerConfig.interruptEn = ENABLE; /*! 使能定时器中断 */
- timerConfig.timerEn = ENABLE; /*! 打开定时器 */
- timerConfig.callBack = test_timer_cb; /*! 中断回调函数 */
- TIMER_Init(TIMER_CHANNEL0, &timerConfig); /*! TIMER初始化函数生效 */
- }
- int main(void)
- {
- InitDelay();
- test_ledinit();
- test_timer_init();
- while (1)
- {
- }
- }
运行效果
3.6 SPI驱动LCD屏幕以前用别的芯片驱动过,文件复制过来改一下SPI通讯部分就行了,放上移植修改的代码,软硬件SPI都能用
- /*
- MOSI PB3
- SCK PB5
- CS PA7
- RST PA8
- A0 PA9
- */
- #define YUYY_USE_SOFT_SPI 0
- void yuyy_hs12864g18b_spiinit(void)
- {
- GPIO_SetFunc(GPIOA, GPIO_PIN7, GPIO_FUN0);/*功能复用选择.*/
- GPIO_SetFunc(GPIOA, GPIO_PIN8, GPIO_FUN0);
- GPIO_SetFunc(GPIOA, GPIO_PIN9, GPIO_FUN0);
- GPIO_SetDir(GPIOA, GPIO_PIN7, GPIO_OUT);
- GPIO_SetDir(GPIOA, GPIO_PIN8, GPIO_OUT);
- GPIO_SetDir(GPIOA, GPIO_PIN9, GPIO_OUT);
-
- GPIO_SetPinLevel(GPIOA, GPIO_PIN6, GPIO_LEVEL_HIGH);
- GPIO_SetPinLevel(GPIOA, GPIO_PIN8, GPIO_LEVEL_HIGH);
-
- #if(YUYY_USE_SOFT_SPI)
- GPIO_SetFunc(GPIOB, GPIO_PIN5, GPIO_FUN0); /*! SCK */
- GPIO_SetFunc(GPIOB, GPIO_PIN3, GPIO_FUN0); /*! MOSI */
- GPIO_SetDir(GPIOB, GPIO_PIN5, GPIO_OUT);
- GPIO_SetDir(GPIOB, GPIO_PIN3, GPIO_OUT);
- GPIO_SetPinLevel(GPIOB, GPIO_PIN5, GPIO_LEVEL_HIGH);
- #else
- SPI_ConfigType spiConfig; /*! SPI配置结构体*/
- /*! 初始化SPI引脚,功能复用选择.*/
- GPIO_SetFunc(GPIOB, GPIO_PIN5, GPIO_FUN3); /*! SCK */
- GPIO_SetFunc(GPIOB, GPIO_PIN3, GPIO_FUN3); /*! MOSI */
- /*! 清零配置结构体变量.*/
- memset(&spiConfig, 0x00, sizeof(spiConfig));
- /*! 初始化SPI参数,波特率 = 2Mbps = (F_BCLK / (SCK_LOW+1 + SCK_HIGH+1)).*/
- spiConfig.sckHigh = 3; /*! SCK高电平时间 = (SCK_HIGH + 1) * CLK_PERIOD.*/
- spiConfig.sckLow = 3; /*! SCK低电平时间 = (SCK_LOW + 1) * CLK_PERIOD.*/
- spiConfig.mode = SPI_MASTER; /*! 设置为主机模式*/
- spiConfig.cpha = SPI_CPHA_2EDGE; /*! 设置数据采样相位,第2个边沿采样数据*/
- spiConfig.cpol = SPI_CPOL_HIGH; /*! 设置SCK空闲时极性,空闲时SCK为高*/
- spiConfig.frmSize = SPI_FRAME_SIZE_8BITS;
- spiConfig.rxMsbFirstEn = ENABLE; /*! 选择从最高位开始接收*/
- spiConfig.txMsbFirstEn = ENABLE; /*! 选择从最高位开始发送*/
- spiConfig.csOutputEn = DISABLE; /*! CS由SPI软件控制*/
- spiConfig.continuousCSEn = ENABLE; /*! 片选连续模式*/
- spiConfig.modeFaultEn = DISABLE; /*! 模式故障禁止*/
- spiConfig.wakeUpEn = DISABLE; /*! 主机模式不支持唤醒功能*/
- spiConfig.spiEn = ENABLE;
- spiConfig.interruptEn = DISABLE; /*! 使能NVIC中断*/
- spiConfig.txUFInterruptEn = DISABLE; /*! 打开TXUF中断,可禁止*/
- spiConfig.rxOFInterruptEn = DISABLE; /*! 打开RXOF中断,可禁止*/
- spiConfig.modeFaultInterruptEn = DISABLE; /*! 关闭模式故障中断*/
- SPI_Init(SPI0, &spiConfig);
- #endif
- }
- void yuyy_hs12864g18b_cs(uint8_t lev)
- {
- GPIO_SetPinLevel(GPIOA, GPIO_PIN7, (lev == 0 ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH));
- }
- void yuyy_hs12864g18b_rst(uint8_t lev)
- {
- GPIO_SetPinLevel(GPIOA, GPIO_PIN8, (lev == 0 ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH));
- }
- void yuyy_hs12864g18b_a0(uint8_t lev)
- {
- GPIO_SetPinLevel(GPIOA, GPIO_PIN9, (lev == 0 ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH));
- }
- void yuyy_hs12864g18b_spiwritebyte(uint8_t dat)
- {
- #if(YUYY_USE_SOFT_SPI)
- uint8_t i = 0;
- while(i<8)
- {
- GPIO_SetPinLevel(GPIOB, GPIO_PIN5, GPIO_LEVEL_LOW);
- if(dat & 0x80)
- GPIO_SetPinLevel(GPIOB, GPIO_PIN3, GPIO_LEVEL_HIGH);
- else
- GPIO_SetPinLevel(GPIOB, GPIO_PIN3, GPIO_LEVEL_LOW);
-
- GPIO_SetPinLevel(GPIOB, GPIO_PIN5, GPIO_LEVEL_HIGH);
- dat <<= 1;
- i++;
- }
- #else
- SPI_TransmitPoll(SPI0, &dat,1);
- #endif
- }
- void yuyy_hs12864g18b_delayus(uint16_t us)
- {
- udelay(us);
- }
运行效果
3.7 I2C读取DHTC12
以前也用别的芯片驱动过,文件复制过来改一下I2C通讯部分就行了
移植修改的代码- #include "ac780x_i2c.h"
- #define DHTC12_IIC I2C0
- #define DHTC12_I2C_ADDR 0x44
- static uint16_t HumA,HumB;
- void yuyy_dhtc12_iic_init(void)
- {
- I2C_ConfigType i2cConfig;
- /*清零结构体变量.*/
- memset(&i2cConfig, 0x00, sizeof(i2cConfig));
- /*初始化引脚功能为I2C.*/
- GPIO_SetFunc(GPIOB, GPIO_PIN7, GPIO_FUN3);
- GPIO_SetFunc(GPIOB, GPIO_PIN8, GPIO_FUN3);
- /*无论是主机还是从机模式都需要配置的参数.*/
- i2cConfig.mode = I2C_MASTER; /*设置主机模式.*/
- i2cConfig.extAddrEn = DISABLE; /*10bit扩展地址禁能.*/
- i2cConfig.interruptEn = DISABLE; /*I2C中断,BND/SAMF/ARBLOST.*/
- i2cConfig.nackInterruptEn = DISABLE; /*NACK中断.*/
- i2cConfig.ssInterruptEn = DISABLE; /*总线start或stop中断.*/
- i2cConfig.i2cEn = ENABLE; /*使能模块.*/
- i2cConfig.callBack = NULL; /*中断回调函数.*/
- /*主机模式需要配置的参数,配置成从机模式可忽略.*/
- /*波特率设置
- f = APB时钟/((sampleCnt+1)*(stepCnt+1)*2)
- 当APB时钟为16M,所需波特率为100Kbps
- 可配置半脉冲宽度stepCnt为7,每个采样点宽度sampleCnt为9
- 则波特率 = 16M/((9+1)*(7+1)*2) = 100K
- */
- i2cConfig.masterConfig.sampleCnt = 119; /*设置波特率为100Kbps,bandrate=(16M/(10*8*2))=100Kbps.*/
- i2cConfig.masterConfig.stepCnt = 117;
- i2cConfig.masterConfig.ARBEn = DISABLE; /*设置主机仲裁功能.*/
- i2cConfig.masterConfig.SYNCEn = DISABLE; /*设置主机SCL同步功能.*/
- I2C_Init(DHTC12_IIC, &i2cConfig);
- }
- uint8_t yuyy_dhtc12_iic_senddatas(uint8_t devaddr,uint16_t regaddr,uint8_t regaddrlen,uint8_t *datas,uint8_t datalen)
- {
- uint8_t i = 0,status = I2C_HW_STATUS_ERROR_NULL;
- uint8_t iicdatas[16] = {0};
- if(regaddrlen == 1)
- {
- iicdatas[0] = regaddr&0xFF;
- }
- else if(regaddrlen == 2)
- {
- iicdatas[0] = (regaddr>>8)&0xFF;
- iicdatas[1] = regaddr&0xFF;
- }
- i = regaddrlen;
- while(i < regaddrlen+datalen)
- {
- iicdatas[i] = datas[i-regaddrlen];
- i++;
- }
- status = I2C_MasterTransmitPoll(DHTC12_IIC,devaddr,iicdatas,regaddrlen+datalen,ENABLE);
- return status;
- }
- uint8_t yuyy_dhtc12_iic_readdatas(uint8_t devaddr,uint16_t regaddr,uint8_t regaddrlen,uint8_t *datas,uint8_t datalen)
- {
- uint8_t status = I2C_HW_STATUS_ERROR_NULL;
- uint8_t iicdatas[2] = {0};
- if(regaddrlen > 0)
- {
-
- if(regaddrlen == 1)
- {
- iicdatas[0] = regaddr&0xFF;
- }
- else if(regaddrlen == 2)
- {
- iicdatas[0] = (regaddr>>8)&0xFF;
- iicdatas[1] = regaddr&0xFF;
- }
- status = I2C_MasterTransmitPoll(DHTC12_IIC,devaddr,iicdatas,regaddrlen+datalen,DISABLE);
- }
- if(status == I2C_HW_STATUS_ERROR_NULL)
- {
- I2C_MasterReceivePoll(DHTC12_IIC,devaddr,datas,datalen);
- }
- return status;
- }
- void yuyy_dhtc12_delayms(uint16_t ms)
- {
- mdelay(ms);
- }
运行效果
4.恒温恒湿控制箱模拟实现
综合上面的实验例程,利用开发板资源模拟实现一个恒温恒湿控制箱,使用I2C读取DHTC12测量温湿度,使用2个LED分别表示温度 湿度是否达标,达标则熄灭,不达标则亮起以1秒为周期闪烁,加湿加热时0.5秒内亮两次后0.5秒保持熄灭,除湿降温时0.5秒亮起0.5秒熄灭,通过LCD屏幕显示当前温湿度和升温/降温 加湿/除湿状态,长按按键进入设定模式,旋转电位器调节数值(电位器不能无限旋转所以做不了相对值调节,本来应该用按键或者编码器的)由于没有温度调节和湿度调节装置,因此只能做个简单的模拟,程序里还会有其它问题,包括但不限于:所有操作都放在了一个定时器里没有区分优先级,设置数值立即生效没有做保存与否的功能,没有温湿度的设置值是否合理的检测,鉴于这只是个简单的模拟所以请忽略
部分代码实现
- #define THREFRESHTIMME 200 //2秒
- #define BOX_T_OFFSET 5 //温度误差范围
- #define BOX_H_OFFSET 5 //湿度误差范围
- #define BOX_KEY_LONGPRESSTIME 100//1秒
- /* =========================================== Typedef ============================================ */
- typedef enum
- {
- THState_Normal = 0, //温湿度正常
- THState_High, //温湿度高
- THState_Low //温湿度低
- } THState_t;
- typedef enum
- {
- THWorkingState_Stop = 0, //温湿度控制器不工作
- THWorkingState_Up, //温湿度控制器加湿/升温中
- THWorkingState_Down //温湿度控制器除湿/降温中
- } THWorkingState_t;
- /* ========================================== Variables =========================================== */
- uint8_t g_rxLen = 0; /*!< 串口接收长度变量 */
- uint8_t g_txLen = 0; /*!< 串口发送长度变量 */
- uint8_t g_txCnt = 0;
- uint8_t g_rxBuf[RX_BUF_LEN] = {0}; /*!< 串口接收数组 */
- uint8_t const test16x16dang[];/*"当",0*/
- uint8_t const test16x16qian[];/*"前",1*/
- uint8_t const test16x16mu[];/*"目",2*/
- uint8_t const test16x16biao[];/*"标",3*/
- uint8_t const test16x16jia[];/*"加",0*/
- uint8_t const test16x16chu[];/*"除",1*/
- uint8_t const test16x16shi[];/*"湿",2*/
- uint8_t const test16x16sheng[];/*"升",3*/
- uint8_t const test16x16jiang[];/*"降",4*/
- uint8_t const test16x16wen[];/*"温",5*/
- uint8_t const test16x16zhong[];/*"中",0*/
- uint8_t const test16x16temp[];
- uint8_t box_setting_mode = 0; //0正常工作 1设置温度 2设置湿度
- int16_t box_target_temp = 250; //目标温度25.0
- uint16_t box_target_humi = 500; //目标湿度50.0%
- int16_t box_current_temp = 250; //目标温度25.0
- uint16_t box_current_humi = 500; //目标湿度50.0%
- uint32_t box_timer_count = THREFRESHTIMME;
- THState_t box_temp_state;
- THState_t box_humi_state;
- THWorkingState_t box_temp_controller_state;
- THWorkingState_t box_humi_controller_state;
- uint16_t box_led_temp = 0;
- uint16_t box_led_humi = 0;
- uint8_t box_key_down_count = 0;
- //初始化函数省略
- void box_adc_init();
- void box_ledinit();
- void box_timer_init();
- void box_keyinit();
- //
- void box_refresh_display()
- {
- char out[15];
- uint8_t outlen,col;
- yuyy_hs12864g18b_display_graphic_16x16(0,0,0,(uint8_t *)test16x16dang);
- yuyy_hs12864g18b_display_graphic_16x16(0,0,16,(uint8_t *)test16x16qian);
- memset(out,0,15);
- outlen = sprintf(out,"%.1f%% %.1f",box_current_humi/10.0,box_current_temp/10.0);
- yuyy_hs12864g18b_display_string_8x16(0,0,32,(uint8_t *)out);
- col = 32+8*outlen;
- yuyy_hs12864g18b_display_graphic_16x16(0,0,col,(uint8_t *)test16x16temp);
-
- yuyy_hs12864g18b_display_graphic_16x16(0,2,0,(uint8_t *)test16x16mu);
- yuyy_hs12864g18b_display_graphic_16x16(0,2,16,(uint8_t *)test16x16biao);
- memset(out,0,15);
- outlen = sprintf(out,"%.1f%%",box_target_humi/10.0);
- yuyy_hs12864g18b_display_string_8x16(box_setting_mode==2?1:0,2,32,(uint8_t *)out);
- yuyy_hs12864g18b_display_string_8x16(0,2,32+outlen*8,(uint8_t *)" ");
- outlen += 1;
- col = 32+8*outlen;
- outlen = sprintf(out,"%.1f",box_target_temp/10.0);
- yuyy_hs12864g18b_display_string_8x16(box_setting_mode==1?1:0,2,col,(uint8_t *)out);
- col += 8*outlen;
- yuyy_hs12864g18b_display_graphic_16x16(0,2,col,(uint8_t *)test16x16temp);
- yuyy_hs12864g18b_display_string_8x16(0,2,col+16,(uint8_t *)" ");
-
- col = 0;
- if(box_humi_controller_state != THWorkingState_Stop)
- {
- yuyy_hs12864g18b_display_graphic_16x16(0,4,0,(uint8_t *)(box_humi_controller_state==THWorkingState_Up?test16x16jia:test16x16chu));
- yuyy_hs12864g18b_display_graphic_16x16(0,4,16,(uint8_t *)test16x16shi);
- yuyy_hs12864g18b_display_graphic_16x16(0,4,32,(uint8_t *)test16x16zhong);
- col = 48;
- }
- if(col > 0)
- {
- yuyy_hs12864g18b_display_string_8x16(0,4,col,(uint8_t *)" ");
- col = 64;
- }
- if(box_temp_controller_state != THWorkingState_Stop)
- {
- yuyy_hs12864g18b_display_graphic_16x16(0,4,col,(uint8_t *)(box_temp_controller_state==THWorkingState_Up?test16x16sheng:test16x16jiang));
- yuyy_hs12864g18b_display_graphic_16x16(0,4,col+16,(uint8_t *)test16x16wen);
- yuyy_hs12864g18b_display_graphic_16x16(0,4,col+32,(uint8_t *)test16x16zhong);
- col += 48;
- }
- yuyy_hs12864g18b_display_string_8x16(0,4,col,(uint8_t *)" ");
- yuyy_hs12864g18b_display_string_8x16(0,6,0,(uint8_t *)"Code by yuyy1989");
- }
- void box_get_th()
- {
- yuyy_dhtc12_readHT(&box_current_temp,&box_current_humi);
- if(box_current_temp < box_target_temp - BOX_H_OFFSET)
- {
- box_temp_state = THState_Low;
- }
- else if(box_current_temp > box_target_temp + BOX_H_OFFSET)
- {
- box_temp_state = THState_High;
- }
- else
- {
- box_temp_state = THState_Normal;
- }
- if(box_current_humi < box_target_humi - BOX_H_OFFSET)
- {
- box_humi_state = THState_Low;
- }
- else if(box_current_humi > box_target_humi + BOX_H_OFFSET)
- {
- box_humi_state = THState_High;
- }
- else
- {
- box_humi_state = THState_Normal;
- }
- }
- void box_set_THcontroller(void)
- {
- if(box_temp_state == THState_High)
- {
- //温度高该降温
- if(box_temp_controller_state != THWorkingState_Down)
- {
- box_temp_controller_state = THWorkingState_Down;
- }
- }
- else if(box_temp_state == THState_Low)
- {
- //温度低该升温
- if(box_temp_controller_state != THWorkingState_Up)
- {
- box_temp_controller_state = THWorkingState_Up;
- }
- }
- else
- {
- //温度符合要求停止升降温
- if(box_temp_controller_state != THWorkingState_Stop)
- {
- box_temp_controller_state = THWorkingState_Stop;
- }
- }
- if(box_humi_state == THState_High)
- {
- //湿度高该除湿
- if(box_humi_controller_state != THWorkingState_Down)
- {
- box_humi_controller_state = THWorkingState_Down;
- }
- }
- else if(box_humi_state == THState_Low)
- {
- //湿度低该加湿
- if(box_humi_controller_state != THWorkingState_Up)
- {
- box_humi_controller_state = THWorkingState_Up;
- }
- }
- else
- {
- //湿度符合要求停止除湿加湿
- if(box_humi_controller_state != THWorkingState_Stop)
- {
- box_humi_controller_state = THWorkingState_Stop;
- }
- }
- }
- void box_prockey(void)
- {
- if(GPIO_GetPinLevel(KEYPORT, KEYPIN) == GPIO_LEVEL_LOW)
- {
- if(box_key_down_count<0xFF)
- box_key_down_count += 1;
- if(box_key_down_count == BOX_KEY_LONGPRESSTIME)
- {
- if(box_setting_mode == 0)
- {
- box_setting_mode = 1;
- box_refresh_display();
- }
- else
- {
- box_setting_mode = 0;
- box_timer_count = 0;
- }
- }
- }
- else
- {
- if(box_key_down_count > 3 && box_key_down_count < BOX_KEY_LONGPRESSTIME)
- {
- if(box_setting_mode == 1)
- {
- box_setting_mode = 2;
- }
- else
- {
- box_setting_mode = 1;
- }
- box_refresh_display();
- }
- box_key_down_count = 0;
- }
- }
- void box_THcontroller_run(void) //LED模拟工作状态
- {
- if(box_led_temp < 100)
- {
- box_led_temp += 1;
- }
- else
- {
- box_led_temp = 0;
- }
- if(box_temp_controller_state == THWorkingState_Down)
- {
- box_setled1onoff(box_led_temp<50?1:0);
- }
- else if(box_temp_controller_state == THWorkingState_Up)
- {
- box_setled1onoff((box_led_temp<15||(box_led_temp>=30&&box_led_temp<45
- ))?1:0);
- }
- else
- {
- box_setled1onoff(0);
- }
- if(box_led_humi < 100)
- {
- box_led_humi += 1;
- }
- else
- {
- box_led_humi = 0;
- }
- if(box_humi_controller_state == THWorkingState_Down)
- {
- box_setled2onoff(box_led_humi<50?1:0);
- }
- else if(box_humi_controller_state == THWorkingState_Up)
- {
- box_setled2onoff((box_led_humi<20||(box_led_humi>=40&&box_led_humi<60))?1:0);
- }
- else
- {
- box_setled2onoff(0);
- }
- }
- void box_timer_cb(void *device, uint32_t wpara, uint32_t lpara)
- {
- box_prockey();
- if(box_timer_count > 0)
- {
- box_timer_count -= 1;
- }
- else
- {
- box_timer_count = THREFRESHTIMME;
- box_get_th();
- box_set_THcontroller();
- box_refresh_display();
- }
- if(box_setting_mode == 1)
- {
- box_target_temp = 1000 - box_getadc()/4095.0 * 1000;
- box_refresh_display();
- }
- else if(box_setting_mode == 2)
- {
- box_target_humi = 1000 - box_getadc()/4095.0 * 1000;
- box_refresh_display();
- }
-
- box_THcontroller_run();
- }
- int main(void)
- {
- InitDelay();
- box_adc_init();
- box_ledinit();
- box_timer_init();
- box_keyinit();
- yuyy_dhtc12_init();
- yuyy_hs12864g18b_init();
- yuyy_hs12864g18b_clear_screen();
- while (1)
- {
- }
- }
运行效果
设置目标温湿度
LED指示工作状态,除湿升温状态