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

[复制链接]
1556|5
 楼主| yuyy1989 发表于 2023-5-24 20:49 | 显示全部楼层 |阅读模式
本帖最后由 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.开箱晒图
开发板已收到,发的是京东快递,这盒子真不错
微信图片_20230524193630.jpg 微信图片_20230524193644.jpg
相比盒子来说板子就显得比较小了
微信图片_20230524193704.jpg 微信图片_20230524193654.jpg
2.搭建开发环境
2.1 下载开发资料,直接从活动贴里下载就行,都打包在一起了,本来也想这里也放一份方便下载,但是上传不了那么大的文件,放上活动贴链接吧https://bbs.21ic.com/icview-3299664-1-1.html
QQ截图20230522132541.png
如果想去官网下载,进这个链接https://www.autochips.com/developersr.html?ty=73&tty=79
QQ截图20230524082444.png

解压出来内容如图
QQ截图20230522132639.png
建议先看一下开发板资料里的AC7802x 开发板入门指南.pdf
QQ截图20230522132705.png
2.2 下载MDK并安装https://www.keil.com/download/product/
QQ截图20230522132849.png
2.3 打开AC7802x开发板资料包CMSIS文件夹中的AutoChips.AC7802x_DFP.1.0.0.rar,双击AutoChips.AC7802x_DFP.1.0.0.pack安装
QQ截图20230522133050.png
正确安装后在keil中可以看到AC7802x系列的芯片
QQ截图20230522133204.png
随便打开一个例程进行编译,可以编译成功说明开发环境搭建成功
QQ截图20230522133416.png
3.例程基础实验
3.1 按键点灯实现点击按键切换2个LED交替亮起
查看AC7802x 开发板入门指南.pdf找到LED和按键用到的IO

QQ截图20230522134212.png
复制一个例程,基于这个例程改动,这里复制的是01_GPIO_Basic
改动后的代码
  1. #include "ac780x_gpio.h"
  2. #define LED1PORT    GPIOA
  3. #define LED1PIN     GPIO_PIN2
  4. #define LED2PORT    GPIOA
  5. #define LED2PIN     GPIO_PIN3
  6. #define KEYPORT     GPIOA
  7. #define KEYPIN      GPIO_PIN11
  8. void test_setled1onoff(uint8_t on)
  9. {
  10.     if(on)
  11.         GPIO_SetPinLevel(LED1PORT, LED1PIN, GPIO_LEVEL_HIGH);
  12.     else
  13.         GPIO_SetPinLevel(LED1PORT, LED1PIN, GPIO_LEVEL_LOW);
  14. }

  15. uint8_t test_getled1state(void)
  16. {
  17.     if(GPIO_GetPinLevel(LED1PORT, LED1PIN) == GPIO_LEVEL_HIGH)
  18.         return 1;
  19.     return 0;
  20. }

  21. void test_setled2onoff(uint8_t on)
  22. {
  23.     if(on)
  24.         GPIO_SetPinLevel(LED2PORT, LED2PIN, GPIO_LEVEL_HIGH);
  25.     else
  26.         GPIO_SetPinLevel(LED2PORT, LED2PIN, GPIO_LEVEL_LOW);
  27. }

  28. uint8_t test_getled2state(void)
  29. {
  30.     if(GPIO_GetPinLevel(LED2PORT, LED2PIN) == GPIO_LEVEL_HIGH)
  31.         return 1;
  32.     return 0;
  33. }

  34. void test_ledinit(void)
  35. {
  36.     GPIO_SetFunc(LED1PORT, LED1PIN, GPIO_FUN0);/*功能复用选择.*/
  37.     GPIO_SetFunc(LED2PORT, LED2PIN, GPIO_FUN0);
  38.     /*设置LED引脚为GPIO输出.*/
  39.     GPIO_SetDir(LED1PORT, LED1PIN, GPIO_OUT);
  40.     GPIO_SetDir(LED2PORT, LED2PIN, GPIO_OUT);
  41. }

  42. void test_keyinit(void)
  43. {
  44.     GPIO_SetFunc(KEYPORT, KEYPIN, GPIO_FUN0); /*功能复用选择.*/
  45.     /*设置按键引脚为输入,检测按键动作.*/
  46.     GPIO_SetDir(KEYPORT, KEYPIN, GPIO_IN);    /*设置为输入模式.*/
  47. }

  48. void test_prockey(void)
  49. {
  50.     if(GPIO_GetPinLevel(KEYPORT, KEYPIN) == GPIO_LEVEL_LOW)
  51.     {
  52.         mdelay(30);
  53.         if(GPIO_GetPinLevel(KEYPORT, KEYPIN) == GPIO_LEVEL_LOW)
  54.         {
  55.             while(GPIO_GetPinLevel(KEYPORT, KEYPIN) == GPIO_LEVEL_LOW);
  56.             test_setled1onoff(!test_getled1state());
  57.             test_setled2onoff(!test_getled2state());
  58.         }
  59.     }
  60. }

  61. int main(void)
  62. {
  63.     InitDelay();
  64.     test_ledinit();
  65.     test_keyinit();
  66.     test_setled1onoff(1);
  67.     test_setled2onoff(0);
  68.     while (1)
  69.     {
  70.         test_prockey();
  71.     }
  72. }
编译烧录,烧录前注意选择自己使用的烧录器,建议勾选上Reset and run选项
QQ截图20230524194200.png
运行效果
b7934fbb3bea41a56274ff9462d32cd1 00_00_00-00_00_30~1.gif
3.2 UART串口通信
这个板子自带了USB转串口,通过Type-C数据线连接时,会出现一个串口设备
QQ截图20230524195308.png
打开例程02_UART_Interrupt,查看串口配置

QQ截图20230524195430.png
查看原理图可以看到所用IO和板载的USB转串口使用的IO一致
QQ截图20230524195947.png QQ截图20230524200017.png
编译烧录,打开串口助手,配置好参数,发送字符串会返回和发送相同的字符串
QQ截图20230524195922.png
下面把串口通讯代码合并到点灯的程序里,实现串口命令控制点灯
在串口空闲中断里添加代码

  1. if(g_rxBuf[0] == 'L' && g_rxBuf[1] == 'E' && g_rxBuf[2] == 'D')
  2. {
  3.         if(g_rxBuf[3] == '1')
  4.         {
  5.                 if(g_rxBuf[4] == '0')
  6.                 {
  7.                         test_setled1onoff(0);
  8.                 }
  9.                 else if(g_rxBuf[4] == '1')
  10.                 {
  11.                          test_setled1onoff(1);
  12.                 }
  13.         }
  14.         else if(g_rxBuf[3] == '2')
  15.         {
  16.                 if(g_rxBuf[4] == '0')
  17.                 {
  18.                         test_setled2onoff(0);
  19.                 }
  20.                 else if(g_rxBuf[4] == '1')
  21.                 {
  22.                          test_setled2onoff(1);
  23.                 }
  24.         }
  25. }
运行效果
39ca955127e49036a6276afeb0d586d3 00_00_00-00_00_30.gif
3.3 PWM实现呼吸灯
开发板上的2个LED可以用PWM驱动,基于例程里的PWM示例,做一个两个灯珠交替呼吸的程序
  1. #include "ac780x_gpio.h"
  2. #include "ac780x_pwm.h"
  3. #include "ac780x_pwm_reg.h"
  4. void test_pwm_Init(void)
  5. {
  6.     PWM_ConfigType config;
  7.     PWM_ModulationConfigType pwmConfig;
  8.     PWM_IndependentChConfig independentChConfig[2];

  9.     memset(&config, 0U, sizeof(config));
  10.     memset(&pwmConfig, 0U, sizeof(pwmConfig));
  11.     memset(&independentChConfig, 0U, sizeof(independentChConfig));

  12.     GPIO_SetFunc(GPIOA, GPIO_PIN2, GPIO_FUN1); /* PA2--PWM2_CH1.*/
  13.     GPIO_SetFunc(GPIOA, GPIO_PIN3, GPIO_FUN1); /* PA3--PWM2_CH0.*/

  14.     /*
  15.     边沿对齐PWM模式:
  16.     周期=(MCVR-CNTIN+1)*PWM计数器时钟周期
  17.     脉宽=(CHnV-CNTIN+1)*PWM计数器时钟周期
  18.     中心对齐PWM模式:
  19.     周期=2*(MCVR-CNTIN)*PWM计数器时钟周期
  20.     脉宽=2*(CHnV-CNTIN)*PWM计数器时钟周期
  21.     */
  22.     independentChConfig[0].channel = PWM_CH_0;                         /*独立输出通道选择 */
  23.     independentChConfig[0].chValue = 0;                             /*通道channel值,决定占空比 */
  24.     independentChConfig[0].levelMode = PWM_HIGH_TRUE;                  /*输出PWM高有效,可配置高有效或低有效 */
  25.     independentChConfig[0].polarity = PWM_OUTPUT_POLARITY_ACTIVE_HIGH; /*通道输出极性配置为高有效,PWM Mask后输出为低电平 */
  26.     independentChConfig[0].interruptEn = ENABLE;                       /*通道匹配中断使能位 */
  27.     independentChConfig[0].initLevel = PWM_LOW_LEVEL;                  /*通道初始电平输出配置,该配置受initChOutputEn控制,决定PMM计数器未工作前PWM口的输出电平 */
  28.     independentChConfig[0].triggerEn = DISABLE;                        /*通道匹配触发使能位,在通道值匹配时可产生触发信号用于其他模块的触发信号 */

  29.     independentChConfig[1].channel = PWM_CH_1;                         /*独立输出通道选择 */
  30.     independentChConfig[1].chValue = 0;                             /*通道channel值,决定占空比 */
  31.     independentChConfig[1].levelMode = PWM_HIGH_TRUE;                  /*输出PWM高有效,可配置高有效或低有效 */
  32.     independentChConfig[1].polarity = PWM_OUTPUT_POLARITY_ACTIVE_HIGH; /*通道输出极性配置为高有效,PWM Mask后输出为低电平 */
  33.     independentChConfig[1].interruptEn = ENABLE;                       /*通道匹配中断使能位 */
  34.     independentChConfig[1].initLevel = PWM_LOW_LEVEL;                  /*通道初始电平输出配置,该配置受initChOutputEn控制,决定PMM计数器未工作前PWM口的输出电平 */
  35.     independentChConfig[1].triggerEn = DISABLE;                        /*通道匹配触发使能位,在通道值匹配时可产生触发信号用于其他模块的触发信号 */

  36.     pwmConfig.countMode = PWM_UP_DOWN_COUNT;               /*PWM计数器模式,PWM_UP_COUNT--向上计数模式;PWM_UP_DOWN_COUNT-- 向上/向下计数模式 */
  37.     pwmConfig.independentChannelNum = 2;                   /*独立通道数目*/
  38.     pwmConfig.combineChannelNum = 0;                       /*组合通道对数 */
  39.     pwmConfig.independentChConfig = independentChConfig;   /*独立通道配置赋值 */
  40.     pwmConfig.combineChConfig = NULL;                      /*组合通道配置赋值 */
  41.     pwmConfig.deadtime = 0;                                /*死区时间值,死区功能仅在组合模式下有效  */
  42.     pwmConfig.deadtimePsc = PWM_DEADTIME_DIVID_1;          /*死区时间时钟分频系数,死区功能仅在组合模式下有效 */
  43.     pwmConfig.initChOutputEn = ENABLE;                     /*初始化通道输出使能位,使能后独立PWM模式的 initLevel 和组合模式的ch1stInitLevel和ch2ndInitLevel配置才会生效*/
  44.     pwmConfig.initTriggerEn = DISABLE;                     /*PWM初始值触发使能位 */

  45.     /*
  46.     向上-向下技术模式下,频率计算为:
  47.     freq = pwm_clk/(2*(maxValue - initValue))
  48.     16000/(2*8000) = 1K
  49.     */
  50.     config.mode = PWM_MODE_MODULATION;            /*PWM模式配置,PWM_MODE_MODULATION--PWM调制模式 */
  51.     config.initModeStruct = &pwmConfig;           /*不同模式相应初始化配置结构体赋值 */
  52.     config.clkSource = PWM_CLK_SOURCE_APB;        /*PWM时钟源选择 */
  53.     config.clkPsc = 0;                            /*时钟分频系数 */
  54.     config.initValue = 0;                         /*初始计数值 */
  55.     config.maxValue = 8000;                       /*最大计数值,决定输出波形频率 */
  56.     config.overflowInterrupEn = ENABLE;           /*溢出中断使能位 */
  57.     config.cntOverflowFreq = 0;                   /*溢出中断产生的频率与计数器频率的关系,0表示每次计数器溢出都产生中断,1表示间隔一次,以此类推 */
  58.     config.interruptEn = ENABLE;                  /*PWM总中断使能位  */
  59.     //config.callBack = PWM2_Callback;              /*中断回调函数 */

  60.     PWM_Init(PWM2, &config);

  61. }
  62. int main(void)
  63. {
  64.     uint16_t pwm = 0;
  65.     uint8_t pwmup = 1;
  66.     InitDelay();
  67.     while (1)
  68.     {

  69.         mdelay(2);
  70.         PWM_SetChannelCountValue(PWM2,0,8000 - pwm);
  71.         PWM_SetChannelCountValue(PWM2,1,pwm);
  72.         if(pwmup > 0)
  73.         {
  74.             if(pwm < 8000 - 10)
  75.             {
  76.                 pwm += 10;
  77.             }
  78.             else
  79.             {
  80.                 pwm = 8000;
  81.                 pwmup = 0;
  82.             }
  83.         }
  84.         else
  85.         {
  86.             if(pwm > 10)
  87.             {
  88.                 pwm -= 10;
  89.             }
  90.             else
  91.             {
  92.                 pwm = 0;
  93.                 pwmup = 1;
  94.             }
  95.         }
  96.         
  97.     }
  98. }
运行效果
0076ee00b79295d6424494a2d29f908f 00_00_00-00_00_30.gif
3.4 通过ADC实现使用电位器控制LED亮度
开发板上有个可调电位器,用它来实现旋转旋钮调节LED亮度
  1. #include "ac780x_gpio.h"
  2. #include "ac780x_pwm.h"
  3. #include "ac780x_pwm_reg.h"
  4. #include "ac780x_adc_reg.h"

  5. void test_pwm_Init(void)
  6. {
  7.     //省略,参考上个例程
  8. }

  9. void test_adc_init(void)
  10. {
  11.     ADC_ConfigType adcConfig;                    /*! ADC初始化配置*/
  12.     memset(&adcConfig, 0x00, sizeof(adcConfig)); /*! 清空结构体*/

  13.     /*! ADC输入端口(电位器)配置*/
  14.     GPIO_SetFunc(GPIOA, GPIO_PIN10, GPIO_FUN2); /*! PA10复用为FUN2,为ADC_IN1 ,对应电位器VR1*/

  15.     /*! ADC配置
  16.     ADC固定为12位分辨率,工作模式为MODE1(工作模式内容见参考手册8.4.2章节),规则组扫描+注入组扫描模式多通道单次转换,规则组长度为3,注入组长度为0
  17.     每触发一次进行一次ADC转换,每次转换规则组中的3个通道。
  18.     */
  19.     adcConfig.clkPsc                     = ADC_CLK_PRESCALER_2;  /*! ADC时钟分频设置,Set ADC Clk = APB时钟频率/(clkPsc + 1) = 16M/2 = 8M */
  20.     adcConfig.scanModeEn                 = DISABLE;               /*! 模式配置SCAN:扫描模式使能位 多通道需使能扫描模式,单通道则不需要使能*/
  21.     adcConfig.continuousModeEn           = DISABLE;              /*! 模式配置CONT:连续模式使能位 0:触发一次后只转换一次,1:触发后可连续转换*/
  22.     adcConfig.regularDiscontinuousModeEn = DISABLE;              /*! 模式配置DISCEN:打开规则组间断转换模式*/
  23.     adcConfig.injectDiscontinuousModeEn  = DISABLE;              /*! 模式配置IDISEN:打开注入组间断转换模式*/
  24.     adcConfig.injectAutoModeEn           = DISABLE;              /*! 模式配置IAUTO:自动注入模式*/
  25.     adcConfig.intervalModeEn             = DISABLE;              /*! 模式配置INTERVAL:注入组为间隔转换模式*/
  26.     adcConfig.regularDiscontinuousNum    = 0;                    /*! 规则组子组长度,用于Mode7和Mode8*/
  27.     adcConfig.interruptEn                = DISABLE;              /*! 总中断使能*/
  28.     adcConfig.voltageRef                 = ADC_VOLTAGEREF_VDDA;  /*! ADC参考源选择 */
  29.     adcConfig.regularTriggerMode         = ADC_TRIGGER_INTERNAL; /*! 规则组触发源类型选择*/
  30.     adcConfig.injectTriggerMode          = ADC_TRIGGER_INTERNAL; /*! 注入组触发源类型选择*/
  31.     adcConfig.regularSequenceLength      = 3;                    /*! 规则组长度*/
  32.     adcConfig.injectSequenceLength       = 0;                    /*! 注入组长度*/
  33.     adcConfig.dataAlign                  = ADC_DATA_ALIGN_RIGHT; /*! 数据右对齐*/
  34.     adcConfig.callBack                   = NULL;                 /*! ADC回调函数*/
  35.     adcConfig.powerMode                  = ADC_POWER_ON;         /*! ADC上电*/
  36.     ADC_Init(ADC0, &adcConfig);                                  /*! ADC works Mode Config*/

  37.     /*!
  38.         ADC转换率计算公式:
  39.         总转换时间=(SPT+ 12)/ADC时钟频率+5个APB时钟周期
  40.         备注:
  41.         1.SPT为采样周期个数,具体见下面ADC_SPT_CLK_x。
  42.         2.ADC时钟频率 = APB时钟频率 /(分频系数+1)
  43.         3.7802x ADC支持的最高采样率为250Ksps(即转换时间不低于4us),如果配置采样率高于该值,可能会导致采样结果精度显著减低。
  44.     */
  45.     /*规则组通道转换序列和转换速率配置*/
  46.     ADC_SetRegularGroupChannel(ADC0, ADC_CH_1, ADC_SPT_CLK_33, 0);   /*! 采样&转换时间= (33+12)/8000000 + 5/16000000 ≈ 5.94us */
  47.     /*! Bandgap或T-sensor内部通道配置*/
  48.     ADC_SetInternalChannel(ADC0, ADC_INTERNAL_TSENSOR); /*! 内部电压信号选择(仅在使用了ADC_CH_VIN 时配置) */
  49.     ADC_SetVBufEnableFlag(ADC0, ENABLE);                /*! Bandgap和T-sensor内部通道使能(仅在使用了ADC_CH_VIN 时配置) */
  50. }
  51. uint16_t test_getadc(void)
  52. {
  53.     uint16_t adcvalue = 0;
  54.     ADC_SoftwareStartRegularConvert(ADC0); /*! 软件触发规则组采样*/

  55.     while (!ADC_GetEOCFlag(ADC0, 0)); /*! 等待规则组最后一个通道转换完成*/

  56.     adcvalue = ADC_GetRegularData(ADC0, 0); /*! 获取规则组0的转换值*/
  57.     return adcvalue;
  58. }
  59. int main(void)
  60. {
  61.     uint16_t pwm = 0;
  62.     InitDelay();
  63.     test_adc_init();
  64.     test_pwm_Init();
  65.     while (1)
  66.     {
  67.         mdelay(10);
  68.         pwm = test_getadc()*8000/4095;
  69.         PWM_SetChannelCountValue(PWM2,0,8000 - pwm);
  70.         PWM_SetChannelCountValue(PWM2,1,pwm);
  71.     }
  72. }
运行效果
f5065d11a7b645b6f55536669a011607 00_00_00-00_00_30.gif
3.5 定时器测试
用定时器实现两个LED交替闪烁
  1. #include "ac780x_gpio.h"
  2. #include "ac780x_timer.h"
  3. #define Timer_CLK        (APB_BUS_FREQ)                    /*!定时器时钟为APB时钟 */   
  4. #define TimeoutS(n)      (Timer_CLK*n - 1)          /*!n 秒超时值 */
  5. #define Timeout1ms       (Timer_CLK/1000-1)         /*!1ms超时值 */
  6. #define Timeout500ms     (Timer_CLK/2-1)            /*!500ms超时值 */
  7. //LED相关函数省略
  8. void test_timer_cb(void *device, uint32_t wpara, uint32_t lpara)
  9. {
  10.     test_setled1onoff(!test_getled1state());
  11.     test_setled2onoff(!test_getled2state());
  12. }

  13. void test_timer_init()
  14. {
  15.     TIMER_ConfigType timerConfig;
  16.     memset(&timerConfig, 0, sizeof(timerConfig));

  17.     /*!配置定时器.*/
  18.     timerConfig.periodValue = Timeout500ms;                  /*! 定义超时值为500ms */
  19.     timerConfig.linkModeEn  = DISABLE;                      /*! 禁能链接模式 */
  20.     timerConfig.interruptEn = ENABLE;                       /*! 使能定时器中断 */
  21.     timerConfig.timerEn     = ENABLE;                       /*! 打开定时器 */
  22.     timerConfig.callBack    = test_timer_cb;           /*! 中断回调函数 */

  23.     TIMER_Init(TIMER_CHANNEL0, &timerConfig);               /*! TIMER初始化函数生效 */
  24. }
  25. int main(void)
  26. {
  27.     InitDelay();
  28.     test_ledinit();
  29.     test_timer_init();
  30.     while (1)
  31.     {
  32.     }
  33. }
运行效果
432615bcb20767f56db030fee0a97cbf 00_00_00-00_00_30.gif
3.6 SPI驱动LCD屏幕以前用别的芯片驱动过,文件复制过来改一下SPI通讯部分就行了,放上移植修改的代码,软硬件SPI都能用
  1. /*
  2. MOSI PB3
  3. SCK  PB5
  4. CS   PA7
  5. RST  PA8
  6. A0   PA9
  7. */
  8. #define YUYY_USE_SOFT_SPI 0

  9. void yuyy_hs12864g18b_spiinit(void)
  10. {
  11.     GPIO_SetFunc(GPIOA, GPIO_PIN7, GPIO_FUN0);/*功能复用选择.*/
  12.     GPIO_SetFunc(GPIOA, GPIO_PIN8, GPIO_FUN0);
  13.     GPIO_SetFunc(GPIOA, GPIO_PIN9, GPIO_FUN0);

  14.     GPIO_SetDir(GPIOA, GPIO_PIN7, GPIO_OUT);
  15.     GPIO_SetDir(GPIOA, GPIO_PIN8, GPIO_OUT);
  16.     GPIO_SetDir(GPIOA, GPIO_PIN9, GPIO_OUT);
  17.       
  18.     GPIO_SetPinLevel(GPIOA, GPIO_PIN6, GPIO_LEVEL_HIGH);
  19.     GPIO_SetPinLevel(GPIOA, GPIO_PIN8, GPIO_LEVEL_HIGH);
  20.    
  21.     #if(YUYY_USE_SOFT_SPI)
  22.     GPIO_SetFunc(GPIOB, GPIO_PIN5, GPIO_FUN0);      /*! SCK */
  23.     GPIO_SetFunc(GPIOB, GPIO_PIN3, GPIO_FUN0);      /*! MOSI */
  24.     GPIO_SetDir(GPIOB, GPIO_PIN5, GPIO_OUT);
  25.     GPIO_SetDir(GPIOB, GPIO_PIN3, GPIO_OUT);
  26.     GPIO_SetPinLevel(GPIOB, GPIO_PIN5, GPIO_LEVEL_HIGH);
  27.     #else
  28.     SPI_ConfigType spiConfig; /*! SPI配置结构体*/
  29.     /*! 初始化SPI引脚,功能复用选择.*/
  30.     GPIO_SetFunc(GPIOB, GPIO_PIN5, GPIO_FUN3);      /*! SCK */
  31.     GPIO_SetFunc(GPIOB, GPIO_PIN3, GPIO_FUN3);      /*! MOSI */

  32.     /*! 清零配置结构体变量.*/
  33.     memset(&spiConfig, 0x00, sizeof(spiConfig));
  34.     /*! 初始化SPI参数,波特率 = 2Mbps = (F_BCLK / (SCK_LOW+1 + SCK_HIGH+1)).*/
  35.     spiConfig.sckHigh = 3;                          /*! SCK高电平时间 = (SCK_HIGH + 1) * CLK_PERIOD.*/
  36.     spiConfig.sckLow  = 3;                          /*! SCK低电平时间 = (SCK_LOW + 1) * CLK_PERIOD.*/
  37.     spiConfig.mode          = SPI_MASTER;           /*! 设置为主机模式*/
  38.     spiConfig.cpha          = SPI_CPHA_2EDGE;       /*! 设置数据采样相位,第2个边沿采样数据*/
  39.     spiConfig.cpol          = SPI_CPOL_HIGH;        /*! 设置SCK空闲时极性,空闲时SCK为高*/
  40.     spiConfig.frmSize       = SPI_FRAME_SIZE_8BITS;
  41.     spiConfig.rxMsbFirstEn  = ENABLE;               /*! 选择从最高位开始接收*/
  42.     spiConfig.txMsbFirstEn  = ENABLE;               /*! 选择从最高位开始发送*/
  43.     spiConfig.csOutputEn    = DISABLE;               /*! CS由SPI软件控制*/
  44.     spiConfig.continuousCSEn = ENABLE;              /*! 片选连续模式*/
  45.     spiConfig.modeFaultEn   = DISABLE;              /*! 模式故障禁止*/
  46.     spiConfig.wakeUpEn      = DISABLE;              /*! 主机模式不支持唤醒功能*/
  47.     spiConfig.spiEn         = ENABLE;
  48.     spiConfig.interruptEn       = DISABLE;           /*! 使能NVIC中断*/
  49.     spiConfig.txUFInterruptEn   = DISABLE;           /*! 打开TXUF中断,可禁止*/
  50.     spiConfig.rxOFInterruptEn   = DISABLE;           /*! 打开RXOF中断,可禁止*/
  51.     spiConfig.modeFaultInterruptEn = DISABLE;       /*! 关闭模式故障中断*/
  52.     SPI_Init(SPI0, &spiConfig);
  53.     #endif
  54. }

  55. void yuyy_hs12864g18b_cs(uint8_t lev)
  56. {
  57.     GPIO_SetPinLevel(GPIOA, GPIO_PIN7, (lev == 0 ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH));
  58. }

  59. void yuyy_hs12864g18b_rst(uint8_t lev)
  60. {
  61.     GPIO_SetPinLevel(GPIOA, GPIO_PIN8, (lev == 0 ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH));
  62. }

  63. void yuyy_hs12864g18b_a0(uint8_t lev)
  64. {
  65.     GPIO_SetPinLevel(GPIOA, GPIO_PIN9, (lev == 0 ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH));
  66. }

  67. void yuyy_hs12864g18b_spiwritebyte(uint8_t dat)
  68. {
  69.     #if(YUYY_USE_SOFT_SPI)
  70.     uint8_t i = 0;
  71.     while(i<8)
  72.     {
  73.         GPIO_SetPinLevel(GPIOB, GPIO_PIN5, GPIO_LEVEL_LOW);
  74.         if(dat & 0x80)
  75.             GPIO_SetPinLevel(GPIOB, GPIO_PIN3, GPIO_LEVEL_HIGH);
  76.         else
  77.             GPIO_SetPinLevel(GPIOB, GPIO_PIN3, GPIO_LEVEL_LOW);
  78.         
  79.         GPIO_SetPinLevel(GPIOB, GPIO_PIN5, GPIO_LEVEL_HIGH);
  80.         dat <<= 1;
  81.         i++;
  82.     }
  83.     #else
  84.     SPI_TransmitPoll(SPI0, &dat,1);
  85.     #endif
  86. }

  87. void yuyy_hs12864g18b_delayus(uint16_t us)
  88. {
  89.         udelay(us);
  90. }
运行效果
微信图片_20230526101211.jpg
3.7 I2C读取DHTC12
以前也用别的芯片驱动过,文件复制过来改一下I2C通讯部分就行了
移植修改的代码
  1. #include "ac780x_i2c.h"
  2. #define DHTC12_IIC I2C0
  3. #define DHTC12_I2C_ADDR 0x44
  4. static uint16_t HumA,HumB;
  5. void yuyy_dhtc12_iic_init(void)
  6. {
  7.     I2C_ConfigType i2cConfig;

  8.     /*清零结构体变量.*/
  9.     memset(&i2cConfig, 0x00, sizeof(i2cConfig));

  10.     /*初始化引脚功能为I2C.*/
  11.     GPIO_SetFunc(GPIOB, GPIO_PIN7, GPIO_FUN3);
  12.     GPIO_SetFunc(GPIOB, GPIO_PIN8, GPIO_FUN3);

  13.     /*无论是主机还是从机模式都需要配置的参数.*/
  14.     i2cConfig.mode              = I2C_MASTER;    /*设置主机模式.*/
  15.     i2cConfig.extAddrEn         = DISABLE;       /*10bit扩展地址禁能.*/
  16.     i2cConfig.interruptEn       = DISABLE;       /*I2C中断,BND/SAMF/ARBLOST.*/
  17.     i2cConfig.nackInterruptEn   = DISABLE;       /*NACK中断.*/
  18.     i2cConfig.ssInterruptEn     = DISABLE;       /*总线start或stop中断.*/
  19.     i2cConfig.i2cEn             = ENABLE;        /*使能模块.*/
  20.     i2cConfig.callBack          = NULL;          /*中断回调函数.*/

  21.     /*主机模式需要配置的参数,配置成从机模式可忽略.*/
  22.     /*波特率设置
  23.     f = APB时钟/((sampleCnt+1)*(stepCnt+1)*2)
  24.     当APB时钟为16M,所需波特率为100Kbps
  25.     可配置半脉冲宽度stepCnt为7,每个采样点宽度sampleCnt为9
  26.     则波特率 = 16M/((9+1)*(7+1)*2) = 100K
  27.     */

  28.     i2cConfig.masterConfig.sampleCnt = 119;        /*设置波特率为100Kbps,bandrate=(16M/(10*8*2))=100Kbps.*/
  29.     i2cConfig.masterConfig.stepCnt   = 117;
  30.     i2cConfig.masterConfig.ARBEn     = DISABLE;   /*设置主机仲裁功能.*/
  31.     i2cConfig.masterConfig.SYNCEn    = DISABLE;   /*设置主机SCL同步功能.*/

  32.     I2C_Init(DHTC12_IIC, &i2cConfig);
  33. }

  34. uint8_t yuyy_dhtc12_iic_senddatas(uint8_t devaddr,uint16_t regaddr,uint8_t regaddrlen,uint8_t *datas,uint8_t datalen)
  35. {
  36.     uint8_t i = 0,status = I2C_HW_STATUS_ERROR_NULL;
  37.     uint8_t iicdatas[16] = {0};
  38.     if(regaddrlen == 1)
  39.     {
  40.         iicdatas[0] = regaddr&0xFF;
  41.     }
  42.     else if(regaddrlen == 2)
  43.     {
  44.         iicdatas[0] = (regaddr>>8)&0xFF;
  45.         iicdatas[1] = regaddr&0xFF;
  46.     }
  47.     i = regaddrlen;
  48.     while(i < regaddrlen+datalen)
  49.     {
  50.         iicdatas[i] = datas[i-regaddrlen];
  51.         i++;
  52.     }
  53.     status = I2C_MasterTransmitPoll(DHTC12_IIC,devaddr,iicdatas,regaddrlen+datalen,ENABLE);
  54.     return status;
  55. }
  56. uint8_t yuyy_dhtc12_iic_readdatas(uint8_t devaddr,uint16_t regaddr,uint8_t regaddrlen,uint8_t *datas,uint8_t datalen)
  57. {
  58.     uint8_t status = I2C_HW_STATUS_ERROR_NULL;
  59.     uint8_t iicdatas[2] = {0};
  60.     if(regaddrlen > 0)
  61.     {
  62.         
  63.         if(regaddrlen == 1)
  64.         {
  65.             iicdatas[0] = regaddr&0xFF;
  66.         }
  67.         else if(regaddrlen == 2)
  68.         {
  69.             iicdatas[0] = (regaddr>>8)&0xFF;
  70.             iicdatas[1] = regaddr&0xFF;
  71.         }
  72.         status = I2C_MasterTransmitPoll(DHTC12_IIC,devaddr,iicdatas,regaddrlen+datalen,DISABLE);
  73.     }
  74.     if(status == I2C_HW_STATUS_ERROR_NULL)
  75.     {
  76.         I2C_MasterReceivePoll(DHTC12_IIC,devaddr,datas,datalen);
  77.     }
  78.     return status;
  79. }
  80. void yuyy_dhtc12_delayms(uint16_t ms)
  81. {
  82.     mdelay(ms);
  83. }

运行效果
微信图片_20230526153818.jpg
4.恒温恒湿控制箱模拟实现

综合上面的实验例程,利用开发板资源模拟实现一个恒温恒湿控制箱,使用I2C读取DHTC12测量温湿度,使用2个LED分别表示温度 湿度是否达标,达标则熄灭,不达标则亮起以1秒为周期闪烁,加湿加热时0.5秒内亮两次后0.5秒保持熄灭,除湿降温时0.5秒亮起0.5秒熄灭,通过LCD屏幕显示当前温湿度和升温/降温 加湿/除湿状态,长按按键进入设定模式,旋转电位器调节数值(电位器不能无限旋转所以做不了相对值调节,本来应该用按键或者编码器的)由于没有温度调节和湿度调节装置,因此只能做个简单的模拟,程序里还会有其它问题,包括但不限于:所有操作都放在了一个定时器里没有区分优先级,设置数值立即生效没有做保存与否的功能,没有温湿度的设置值是否合理的检测,鉴于这只是个简单的模拟所以请忽略
部分代码实现
  1. #define THREFRESHTIMME 200 //2秒
  2. #define BOX_T_OFFSET 5 //温度误差范围
  3. #define BOX_H_OFFSET 5 //湿度误差范围
  4. #define BOX_KEY_LONGPRESSTIME 100//1秒
  5. /* ===========================================  Typedef  ============================================ */
  6. typedef enum
  7. {
  8.     THState_Normal = 0,   //温湿度正常
  9.     THState_High,         //温湿度高
  10.     THState_Low           //温湿度低
  11. } THState_t;

  12. typedef enum
  13. {
  14.     THWorkingState_Stop = 0,   //温湿度控制器不工作
  15.     THWorkingState_Up,         //温湿度控制器加湿/升温中
  16.     THWorkingState_Down        //温湿度控制器除湿/降温中
  17. } THWorkingState_t;

  18. /* ==========================================  Variables  =========================================== */
  19. uint8_t g_rxLen  = 0;                 /*!< 串口接收长度变量 */        
  20. uint8_t g_txLen  = 0;                 /*!< 串口发送长度变量 */
  21. uint8_t g_txCnt  = 0;
  22. uint8_t g_rxBuf[RX_BUF_LEN] = {0};    /*!< 串口接收数组 */

  23. uint8_t const test16x16dang[];/*"当",0*/
  24. uint8_t const test16x16qian[];/*"前",1*/
  25. uint8_t const test16x16mu[];/*"目",2*/
  26. uint8_t const test16x16biao[];/*"标",3*/
  27. uint8_t const test16x16jia[];/*"加",0*/
  28. uint8_t const test16x16chu[];/*"除",1*/
  29. uint8_t const test16x16shi[];/*"湿",2*/
  30. uint8_t const test16x16sheng[];/*"升",3*/
  31. uint8_t const test16x16jiang[];/*"降",4*/
  32. uint8_t const test16x16wen[];/*"温",5*/
  33. uint8_t const test16x16zhong[];/*"中",0*/
  34. uint8_t const test16x16temp[];

  35. uint8_t box_setting_mode = 0;    //0正常工作 1设置温度 2设置湿度
  36. int16_t box_target_temp = 250;    //目标温度25.0
  37. uint16_t box_target_humi = 500;  //目标湿度50.0%
  38. int16_t box_current_temp = 250;    //目标温度25.0
  39. uint16_t box_current_humi = 500;  //目标湿度50.0%
  40. uint32_t box_timer_count = THREFRESHTIMME;
  41. THState_t box_temp_state;
  42. THState_t box_humi_state;
  43. THWorkingState_t box_temp_controller_state;
  44. THWorkingState_t box_humi_controller_state;
  45. uint16_t box_led_temp = 0;
  46. uint16_t box_led_humi = 0;
  47. uint8_t box_key_down_count = 0;
  48. //初始化函数省略
  49. void box_adc_init();
  50. void box_ledinit();
  51. void box_timer_init();
  52. void box_keyinit();
  53. //
  54. void box_refresh_display()
  55. {
  56.     char out[15];
  57.     uint8_t outlen,col;
  58.     yuyy_hs12864g18b_display_graphic_16x16(0,0,0,(uint8_t *)test16x16dang);
  59.     yuyy_hs12864g18b_display_graphic_16x16(0,0,16,(uint8_t *)test16x16qian);
  60.     memset(out,0,15);
  61.     outlen = sprintf(out,"%.1f%% %.1f",box_current_humi/10.0,box_current_temp/10.0);
  62.     yuyy_hs12864g18b_display_string_8x16(0,0,32,(uint8_t *)out);
  63.     col = 32+8*outlen;
  64.     yuyy_hs12864g18b_display_graphic_16x16(0,0,col,(uint8_t *)test16x16temp);
  65.    
  66.     yuyy_hs12864g18b_display_graphic_16x16(0,2,0,(uint8_t *)test16x16mu);
  67.     yuyy_hs12864g18b_display_graphic_16x16(0,2,16,(uint8_t *)test16x16biao);
  68.     memset(out,0,15);
  69.     outlen = sprintf(out,"%.1f%%",box_target_humi/10.0);
  70.     yuyy_hs12864g18b_display_string_8x16(box_setting_mode==2?1:0,2,32,(uint8_t *)out);
  71.     yuyy_hs12864g18b_display_string_8x16(0,2,32+outlen*8,(uint8_t *)" ");
  72.     outlen += 1;
  73.     col = 32+8*outlen;
  74.     outlen = sprintf(out,"%.1f",box_target_temp/10.0);
  75.     yuyy_hs12864g18b_display_string_8x16(box_setting_mode==1?1:0,2,col,(uint8_t *)out);
  76.     col += 8*outlen;
  77.     yuyy_hs12864g18b_display_graphic_16x16(0,2,col,(uint8_t *)test16x16temp);
  78.     yuyy_hs12864g18b_display_string_8x16(0,2,col+16,(uint8_t *)"  ");
  79.    
  80.     col = 0;
  81.     if(box_humi_controller_state != THWorkingState_Stop)
  82.     {
  83.         yuyy_hs12864g18b_display_graphic_16x16(0,4,0,(uint8_t *)(box_humi_controller_state==THWorkingState_Up?test16x16jia:test16x16chu));
  84.         yuyy_hs12864g18b_display_graphic_16x16(0,4,16,(uint8_t *)test16x16shi);
  85.         yuyy_hs12864g18b_display_graphic_16x16(0,4,32,(uint8_t *)test16x16zhong);
  86.         col = 48;
  87.     }
  88.     if(col > 0)
  89.     {
  90.         yuyy_hs12864g18b_display_string_8x16(0,4,col,(uint8_t *)"  ");
  91.         col = 64;
  92.     }
  93.     if(box_temp_controller_state != THWorkingState_Stop)
  94.     {
  95.         yuyy_hs12864g18b_display_graphic_16x16(0,4,col,(uint8_t *)(box_temp_controller_state==THWorkingState_Up?test16x16sheng:test16x16jiang));
  96.         yuyy_hs12864g18b_display_graphic_16x16(0,4,col+16,(uint8_t *)test16x16wen);
  97.         yuyy_hs12864g18b_display_graphic_16x16(0,4,col+32,(uint8_t *)test16x16zhong);
  98.         col += 48;
  99.     }
  100.     yuyy_hs12864g18b_display_string_8x16(0,4,col,(uint8_t *)"                ");
  101.     yuyy_hs12864g18b_display_string_8x16(0,6,0,(uint8_t *)"Code by yuyy1989");
  102. }
  103. void box_get_th()
  104. {
  105.     yuyy_dhtc12_readHT(&box_current_temp,&box_current_humi);
  106.     if(box_current_temp < box_target_temp - BOX_H_OFFSET)
  107.     {
  108.         box_temp_state = THState_Low;
  109.     }
  110.     else if(box_current_temp > box_target_temp + BOX_H_OFFSET)
  111.     {
  112.         box_temp_state = THState_High;
  113.     }
  114.     else
  115.     {
  116.         box_temp_state = THState_Normal;
  117.     }
  118.     if(box_current_humi < box_target_humi - BOX_H_OFFSET)
  119.     {
  120.         box_humi_state = THState_Low;
  121.     }
  122.     else if(box_current_humi > box_target_humi + BOX_H_OFFSET)
  123.     {
  124.         box_humi_state = THState_High;
  125.     }
  126.     else
  127.     {
  128.         box_humi_state = THState_Normal;
  129.     }
  130. }
  131. void box_set_THcontroller(void)
  132. {
  133.     if(box_temp_state == THState_High)
  134.     {
  135.         //温度高该降温
  136.         if(box_temp_controller_state != THWorkingState_Down)
  137.         {
  138.             box_temp_controller_state = THWorkingState_Down;
  139.         }
  140.     }
  141.     else if(box_temp_state == THState_Low)
  142.     {
  143.         //温度低该升温
  144.         if(box_temp_controller_state != THWorkingState_Up)
  145.         {
  146.             box_temp_controller_state = THWorkingState_Up;
  147.         }
  148.     }
  149.     else
  150.     {
  151.         //温度符合要求停止升降温
  152.         if(box_temp_controller_state != THWorkingState_Stop)
  153.         {
  154.             box_temp_controller_state = THWorkingState_Stop;
  155.         }
  156.     }
  157.     if(box_humi_state == THState_High)
  158.     {
  159.         //湿度高该除湿
  160.         if(box_humi_controller_state != THWorkingState_Down)
  161.         {
  162.             box_humi_controller_state = THWorkingState_Down;
  163.         }
  164.     }
  165.     else if(box_humi_state == THState_Low)
  166.     {
  167.         //湿度低该加湿
  168.         if(box_humi_controller_state != THWorkingState_Up)
  169.         {
  170.             box_humi_controller_state = THWorkingState_Up;
  171.         }
  172.     }
  173.     else
  174.     {
  175.         //湿度符合要求停止除湿加湿
  176.         if(box_humi_controller_state != THWorkingState_Stop)
  177.         {
  178.             box_humi_controller_state = THWorkingState_Stop;
  179.         }
  180.     }
  181. }

  182. void box_prockey(void)
  183. {
  184.     if(GPIO_GetPinLevel(KEYPORT, KEYPIN) == GPIO_LEVEL_LOW)
  185.     {
  186.         if(box_key_down_count<0xFF)
  187.             box_key_down_count += 1;
  188.         if(box_key_down_count == BOX_KEY_LONGPRESSTIME)
  189.         {
  190.             if(box_setting_mode == 0)
  191.             {
  192.                 box_setting_mode = 1;
  193.                 box_refresh_display();
  194.             }
  195.             else
  196.             {
  197.                 box_setting_mode = 0;
  198.                 box_timer_count = 0;
  199.             }
  200.         }
  201.     }
  202.     else
  203.     {
  204.         if(box_key_down_count > 3 && box_key_down_count < BOX_KEY_LONGPRESSTIME)
  205.         {
  206.             if(box_setting_mode == 1)
  207.             {
  208.                 box_setting_mode = 2;
  209.             }
  210.             else
  211.             {
  212.                 box_setting_mode = 1;
  213.             }
  214.             box_refresh_display();
  215.         }
  216.         box_key_down_count = 0;
  217.     }
  218. }

  219. void box_THcontroller_run(void) //LED模拟工作状态
  220. {
  221.     if(box_led_temp < 100)
  222.     {
  223.         box_led_temp += 1;
  224.     }
  225.     else
  226.     {
  227.         box_led_temp = 0;
  228.     }
  229.     if(box_temp_controller_state == THWorkingState_Down)
  230.     {
  231.         box_setled1onoff(box_led_temp<50?1:0);
  232.     }
  233.     else if(box_temp_controller_state == THWorkingState_Up)
  234.     {
  235.         box_setled1onoff((box_led_temp<15||(box_led_temp>=30&&box_led_temp<45
  236.         ))?1:0);
  237.     }
  238.     else
  239.     {
  240.         box_setled1onoff(0);
  241.     }
  242.     if(box_led_humi < 100)
  243.     {
  244.         box_led_humi += 1;
  245.     }
  246.     else
  247.     {
  248.         box_led_humi = 0;
  249.     }
  250.     if(box_humi_controller_state == THWorkingState_Down)
  251.     {
  252.         box_setled2onoff(box_led_humi<50?1:0);
  253.     }
  254.     else if(box_humi_controller_state == THWorkingState_Up)
  255.     {
  256.         box_setled2onoff((box_led_humi<20||(box_led_humi>=40&&box_led_humi<60))?1:0);
  257.     }
  258.     else
  259.     {
  260.         box_setled2onoff(0);
  261.     }
  262. }

  263. void box_timer_cb(void *device, uint32_t wpara, uint32_t lpara)
  264. {
  265.     box_prockey();
  266.     if(box_timer_count > 0)
  267.     {
  268.         box_timer_count -= 1;
  269.     }
  270.     else
  271.     {
  272.         box_timer_count = THREFRESHTIMME;
  273.         box_get_th();
  274.         box_set_THcontroller();
  275.         box_refresh_display();
  276.     }
  277.     if(box_setting_mode == 1)
  278.     {
  279.         box_target_temp = 1000 - box_getadc()/4095.0 * 1000;
  280.         box_refresh_display();
  281.     }
  282.     else if(box_setting_mode == 2)
  283.     {
  284.         box_target_humi = 1000 - box_getadc()/4095.0 * 1000;
  285.         box_refresh_display();
  286.     }
  287.         
  288.     box_THcontroller_run();
  289. }

  290. int main(void)
  291. {
  292.     InitDelay();
  293.     box_adc_init();
  294.     box_ledinit();
  295.     box_timer_init();
  296.     box_keyinit();
  297.     yuyy_dhtc12_init();
  298.     yuyy_hs12864g18b_init();
  299.     yuyy_hs12864g18b_clear_screen();
  300.     while (1)
  301.     {        
  302.     }
  303. }
运行效果
微信图片_20230527202427.jpg
设置目标温湿度
6c99c792755a3684bed1ac76ffd8b3f7 00_00_00-00_00_30.gif
LED指示工作状态,除湿升温状态 2e811a194a0c5d61f5cc999c94089ff1 00_00_00-00_00_30.gif









 楼主| yuyy1989 发表于 2023-5-25 15:56 | 显示全部楼层
本帖最后由 yuyy1989 于 2023-5-25 17:03 编辑

啥时候论坛发帖能直接上传视频啊,转成的GIF比原视频都大
QQ截图20230525155518.png
hehung 发表于 2023-5-25 16:23 | 显示全部楼层
你这动作太快了吧
lulugl 发表于 2023-5-26 08:50 | 显示全部楼层
你这是开了挂了吗?速度那个快呀!
 楼主| yuyy1989 发表于 2023-5-26 09:25 | 显示全部楼层
lulugl 发表于 2023-5-26 08:50
你这是开了挂了吗?速度那个快呀!

程序代码都是参考例程的很简单
lulugl 发表于 2023-5-26 09:58 | 显示全部楼层
yuyy1989 发表于 2023-5-26 09:25
程序代码都是参考例程的很简单

我还在努力的学习数据手册之中。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部