打印
[活动专区]

【杰发科技AC7802x测评】开箱环境搭建基础实验+模拟实现恒温恒湿控制箱

[复制链接]
871|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 yuyy1989 于 2023-6-1 14:34 编辑

本帖内容
1.开箱晒图
2.搭建开发环境
2.1 下载开发资料
2.2 下载MDK并安装
2.3 安装AutoChips.AC7802x_DFP.1.0.0.pack
3.例程基础实验
3.1 按键点灯
3.2 UART串口通信
3.3 PWM实现呼吸灯
3.4 通过ADC实现使用电位器控制LED亮度
3.5 定时器测试
3.6 SPI驱动LCD屏幕
3.7 I2C读取DHTC12
4.恒温恒湿控制箱模拟实现
1.开箱晒图
开发板已收到,发的是京东快递,这盒子真不错

相比盒子来说板子就显得比较小了

2.搭建开发环境
2.1 下载开发资料,直接从活动贴里下载就行,都打包在一起了,本来也想这里也放一份方便下载,但是上传不了那么大的文件,放上活动贴链接吧https://bbs.21ic.com/icview-3299664-1-1.html

如果想去官网下载,进这个链接https://www.autochips.com/developersr.html?ty=73&tty=79


解压出来内容如图

建议先看一下开发板资料里的AC7802x 开发板入门指南.pdf

2.2 下载MDK并安装https://www.keil.com/download/product/

2.3 打开AC7802x开发板资料包CMSIS文件夹中的AutoChips.AC7802x_DFP.1.0.0.rar,双击AutoChips.AC7802x_DFP.1.0.0.pack安装

正确安装后在keil中可以看到AC7802x系列的芯片

随便打开一个例程进行编译,可以编译成功说明开发环境搭建成功

3.例程基础实验
3.1 按键点灯实现点击按键切换2个LED交替亮起
查看AC7802x 开发板入门指南.pdf找到LED和按键用到的IO


复制一个例程,基于这个例程改动,这里复制的是01_GPIO_Basic
改动后的代码
#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指示工作状态,除湿升温状态









使用特权

评论回复

相关帖子

沙发
yuyy1989|  楼主 | 2023-5-25 15:56 | 只看该作者
本帖最后由 yuyy1989 于 2023-5-25 17:03 编辑

啥时候论坛发帖能直接上传视频啊,转成的GIF比原视频都大

使用特权

评论回复
板凳
hehung| | 2023-5-25 16:23 | 只看该作者
你这动作太快了吧

使用特权

评论回复
地板
lulugl| | 2023-5-26 08:50 | 只看该作者
你这是开了挂了吗?速度那个快呀!

使用特权

评论回复
5
yuyy1989|  楼主 | 2023-5-26 09:25 | 只看该作者
lulugl 发表于 2023-5-26 08:50
你这是开了挂了吗?速度那个快呀!

程序代码都是参考例程的很简单

使用特权

评论回复
6
lulugl| | 2023-5-26 09:58 | 只看该作者
yuyy1989 发表于 2023-5-26 09:25
程序代码都是参考例程的很简单

我还在努力的学习数据手册之中。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

149

主题

708

帖子

7

粉丝