[AT32M412] 【AT-START-M412测评】+孵化控制器

[复制链接]
 楼主| gaoyang9992006 发表于 2025-6-16 12:40 | 显示全部楼层 |阅读模式
本帖最后由 gaoyang9992006 于 2025-6-16 12:42 编辑

【AT-START-M412测评】+给开发板做了一个扩展板                       https://bbs.21ic.com/icview-3461506-1-1.html
【AT-START-M412测评】+ 按钮学习,IO中断,为何下降沿不中断    https://bbs.21ic.com/icview-3461522-1-1.html
【AT-START-M412测评】+ 按钮学习,多路IO中断                            https://bbs.21ic.com/icview-3461668-1-1.html
【AT-START-M412测评】+点亮SSD1306的OLED屏                            https://bbs.21ic.com/icview-3461734-1-1.html

经过今天一上午的学习和实验,终于将之前我做过的东西合并成了一个 可以用的鸡蛋孵化控制器。
该电路包含了四部分:IO输入中断功能实现的按键部分;I2C接口的显示器部分;ADC检测NTC温度传感器部分;IO输出控制部分。

总体main.c代码如下所示


  1. #include "at32m412_416_board.h"
  2. #include "at32m412_416_clock.h"
  3. #include "i2c_application.h"
  4. #include "oled.h"
  5. #include "at32m412_416_adc.h"
  6.         #include  "NTC.h"


  7. extern i2c_handle_type hi2cx;


  8. #define DELAY                            100
  9. #define FAST                             1
  10. #define SLOW                             4

  11. uint8_t g_speed = FAST;
  12. uint8_t ioIndex =0x00;
  13. void button_exint_init(void);

  14. void button_B4_isr(void);
  15. void button_B5_isr(void);
  16. void button_B7_isr(void);
  17. void button_B10_isr(void);

  18. void Write_IIC_Command(unsigned char IIC_Command);
  19. void Write_IIC_Data(unsigned char IIC_Data);
  20. void OLED_WR_Byte(unsigned dat,unsigned cmd);
  21. void i2c_lowlevel_init(i2c_handle_type* hi2c);


  22. /**
  23.   * [url=home.php?mod=space&uid=247401]@brief[/url]  configure button exint
  24.   * @param  none
  25.   * @retval none
  26.   */
  27. //void button_exint_init(void)
  28. //{
  29. //  exint_init_type exint_init_struct;

  30. //  crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
  31. //   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOA, SCFG_PINS_SOURCE0);

  32. //  exint_default_para_init(&exint_init_struct);
  33. //  exint_init_struct.line_enable = TRUE;
  34. //  exint_init_struct.line_mode = EXINT_LINE_INTERRUPT;
  35. //  exint_init_struct.line_select = EXINT_LINE_0;
  36. //  exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  37. //  exint_init(&exint_init_struct);

  38. //  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  39. //  nvic_irq_enable(EXINT0_IRQn, 0, 0);
  40. //}
  41. void button_exint_init(void)
  42. {
  43.   exint_init_type exint_init_struct;

  44.   crm_periph_clock_enable(CRM_SCFG_PERIPH_CLOCK, TRUE);
  45.   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE4);
  46.   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE5);  
  47.   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE7);
  48.   scfg_exint_line_config(SCFG_PORT_SOURCE_GPIOB, SCFG_PINS_SOURCE10);
  49.   
  50.   exint_default_para_init(&exint_init_struct);
  51.   exint_init_struct.line_enable = TRUE;
  52.   exint_init_struct.line_mode = EXINT_LINE_INTERRUPT;
  53.   exint_init_struct.line_select = EXINT_LINE_4 | EXINT_LINE_5 | EXINT_LINE_7 | EXINT_LINE_10;
  54.   exint_init_struct.line_polarity = EXINT_TRIGGER_FALLING_EDGE;
  55.   exint_init(&exint_init_struct);
  56.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  57.   nvic_irq_enable(EXINT4_IRQn, 0, 0);
  58.   nvic_irq_enable(EXINT9_5_IRQn, 0, 0);
  59.   nvic_irq_enable(EXINT15_10_IRQn, 0, 0);
  60. }
  61. /**
  62.   * [url=home.php?mod=space&uid=247401]@brief[/url]  button handler function
  63.   * @param  none
  64.   * @retval none
  65.   */
  66. void button_B4_isr(void)
  67. {
  68.   /* delay 5ms */
  69.   delay_ms(5);

  70.   /* clear interrupt pending bit */
  71.   exint_flag_clear(EXINT_LINE_4);

  72.   /* check input pin state */
  73.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_4))
  74.   {
  75.     ioIndex = 0x03;
  76.   }
  77.   printf("GPIOB_04 is pressed.\r\n");
  78. }

  79. void button_B5_isr(void)
  80. {
  81.   /* delay 5ms */
  82.   delay_ms(5);

  83.   /* clear interrupt pending bit */
  84.   exint_flag_clear(EXINT_LINE_5);

  85.   /* check input pin state */
  86.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_5))
  87.   {
  88.     ioIndex = 0x04;
  89.     printf("GPIOB_05 is pressed.\r\n");
  90.   }

  91. }

  92. void button_B7_isr(void)
  93. {
  94.   /* delay 5ms */
  95.   delay_ms(5);

  96.   /* clear interrupt pending bit */
  97.   exint_flag_clear(EXINT_LINE_7);

  98.   /* check input pin state */
  99.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_7))
  100.   {
  101.     ioIndex = 0x01;
  102.     printf("GPIOB_07 is pressed.\r\n");
  103.   }
  104.   
  105. }

  106. void button_B10_isr(void)
  107. {
  108.   /* delay 5ms */
  109.   delay_ms(5);

  110.   /* clear interrupt pending bit */
  111.   exint_flag_clear(EXINT_LINE_10);

  112.   /* check input pin state */
  113.   if(RESET == gpio_input_data_bit_read(GPIOB, GPIO_PINS_10))
  114.   {
  115.     ioIndex = 0x02;   
  116.     printf("GPIOB_10 is pressed.\r\n");
  117.   }

  118. }


  119. /**
  120.   * [url=home.php?mod=space&uid=247401]@brief[/url]  exint0 interrupt handler
  121.   * @param  none
  122.   * @retval none
  123.   */
  124. void EXINT4_IRQHandler(void)
  125. {
  126.   button_B4_isr();
  127. }
  128. void EXINT9_5_IRQHandler(void)
  129. {
  130.   button_B5_isr();
  131.   button_B7_isr();
  132. }
  133. void EXINT15_10_IRQHandler(void)
  134. {
  135.   button_B10_isr();
  136. }

  137. void disp_static(void)
  138. {
  139.                 u8 i;
  140.         
  141.                 for(i=0; i<5; i++)        WriteHZ16((u8)(i*16+24), 0,i);                //在第1行,显示汉字“科学小火箭”
  142.                 for(i=5; i<7; i++)        WriteHZ16((u8)((i-5)*16),2,i);                //在第2行,显示汉字“设置”
  143.                 for(i=9; i<11; i++)        WriteHZ16((u8)((i-7)*16),2,i);                //在第2行,显示汉字“温度”
  144.                
  145.                 WriteHZ16((u8)(7*16),2,13);                                       //在第2行末尾,显示“℃”
  146.                 WriteHZ16((u8)(7*16),4,13);                                       //在第3行末尾,显示“℃”
  147.         
  148.                 for(i=7; i<11; i++)        WriteHZ16((u8)((i-7)*16),4,i);                //在第3行,显示汉字“当前温度”
  149.                
  150.                 WriteHZ16(0,6,11);                                                //在第4行,显示汉字“第”
  151.                 WriteHZ16(48,6,12);                                               //在第4行,显示汉字“天”
  152. }

  153. static void gpio_config(void)
  154. {
  155.   gpio_init_type gpio_initstructure;
  156.   crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

  157.   gpio_default_para_init(&gpio_initstructure);

  158.   /* 1. 配置ADC引脚(PA1)为模拟输入模式 */
  159.   gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
  160.   gpio_initstructure.gpio_pins = GPIO_PINS_1;
  161.   gpio_init(GPIOA, &gpio_initstructure);
  162.   
  163.   /* 2. 配置PA6为推挽输出模式 */
  164.   gpio_default_para_init(&gpio_initstructure); // 重新初始化结构体
  165.   gpio_initstructure.gpio_pins = GPIO_PINS_6;
  166.   gpio_initstructure.gpio_mode = GPIO_MODE_OUTPUT;
  167.   gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  168.   gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
  169.   gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  170.   gpio_init(GPIOA, &gpio_initstructure);
  171.   
  172.   // 可选:初始化PA6为低电平
  173.   gpio_bits_reset(GPIOA, GPIO_PINS_6);
  174.   
  175. }

  176. static void adc_config(void)
  177. {
  178.   adc_common_config_type adc_common_struct;
  179.   adc_base_config_type adc_base_struct;
  180.   crm_periph_clock_enable(CRM_ADC2_PERIPH_CLOCK, TRUE);

  181.   adc_common_default_para_init(&adc_common_struct);

  182.   /* config combine mode */
  183.   adc_common_struct.combine_mode = ADC_INDEPENDENT_MODE;

  184.   /* config division,adcclk is division by hclk */
  185.   adc_common_struct.div = ADC_HCLK_DIV_6;

  186.   /* config common dma mode,it's not useful in independent mode */
  187.   adc_common_struct.common_dma_mode = ADC_COMMON_DMAMODE_DISABLE;

  188.   /* config common dma request repeat */
  189.   adc_common_struct.common_dma_request_repeat_state = FALSE;

  190.   /* config adjacent adc sampling interval,it's useful for ordinary shifting mode */
  191.   adc_common_struct.sampling_interval = ADC_SAMPLING_INTERVAL_4CYCLES;

  192.   /* config inner temperature sensor and vintrv */
  193.   adc_common_struct.tempervintrv_state = FALSE;
  194.   adc_common_config(&adc_common_struct);

  195.   adc_base_default_para_init(&adc_base_struct);

  196.   adc_base_struct.sequence_mode = TRUE;
  197.   adc_base_struct.repeat_mode = FALSE;
  198.   adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
  199.   adc_base_struct.ordinary_channel_length = 1;
  200.   adc_base_config(ADC2, &adc_base_struct);
  201.   adc_resolution_set(ADC2, ADC_RESOLUTION_12B);

  202.   /* config ordinary channel */
  203.   adc_ordinary_channel_set(ADC2, ADC_CHANNEL_1, 1, ADC_SAMPLETIME_239_5);

  204.   /* adc enable */
  205.   adc_enable(ADC2, TRUE);
  206.   while(adc_flag_get(ADC2, ADC_RDY_FLAG) == RESET);

  207.   /* adc calibration */
  208.   adc_calibration_init(ADC2);
  209.   while(adc_calibration_init_status_get(ADC2));
  210.   adc_calibration_start(ADC2);
  211.   while(adc_calibration_status_get(ADC2));
  212. }
  213. /**
  214.   * @brief  main function.
  215.   * @param  none
  216.   * @retval none

  217.   */

  218. float target_temperature  = 37.8;
  219. float current_temperature = 0;
  220. u8    target_temperature_string[5];//存储目标温度字符串
  221. u8    current_temperature_string[5];//存储当前温度字符串

  222. u8     day_s[3];       //存储天数字符串
  223. u8     adc_temp[5];
  224. u16    adc_result=0;
  225. float Rval;

  226. int time_ms  =0;
  227. int time_s   =50;
  228. int time_min =59;
  229. int time_hour=23;
  230. int time_days=5;

  231. int flag_s = 0;

  232. u8 time_char[9]="12:23:45";//用于存储显示用的 时:分:秒

  233. crm_clocks_freq_type crm_clocks_freq_struct = {0};

  234. int main(void)
  235. {
  236.   system_clock_config();

  237.   at32_board_init();
  238.   button_exint_init();
  239.   gpio_config();
  240.   adc_config();
  241.   hi2cx.i2cx = I2Cx_PORT;
  242.   i2c_config(&hi2cx);
  243.   
  244.   uart_print_init(115200);
  245.   printf("at32 mcu initialize ok.\r\n");
  246.   Initialize_OLED();
  247.   disp_static();
  248.   
  249.   /* get system clock */
  250.   crm_clocks_freq_get(&crm_clocks_freq_struct);
  251.   /* enable tmr1 clock */
  252.   crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
  253.   /* tmr1 configuration */
  254.   /* time base configuration */
  255.   tmr_base_init(TMR1, 999, (crm_clocks_freq_struct.apb2_freq / 1000000) - 1);
  256.   tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);

  257.   /* overflow interrupt enable */
  258.   tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);

  259.   /* tmr1 hall interrupt nvic init */
  260.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  261.   nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 1, 0);
  262.     /* enable tmr1 */
  263.   tmr_counter_enable(TMR1, TRUE);
  264.   while(1)
  265.   {
  266. //    at32_led_toggle(LED2);
  267. //    delay_ms(g_speed * DELAY);
  268. //    at32_led_toggle(LED3);
  269. //    delay_ms(g_speed * DELAY);
  270. //    at32_led_toggle(LED4);
  271. //    delay_ms(g_speed * DELAY);

  272.                 if(ioIndex==0x01)
  273.                 {
  274.                         time_days--;
  275.                         if(time_days<=0) time_days=0;
  276.                         ioIndex=0x00;
  277.                 }
  278.                
  279.                 if(ioIndex==0x02)
  280.                 {
  281.                         time_days++;
  282.                         if(time_days>=50) time_days=0;
  283.                         ioIndex=0x00;
  284.                 }        
  285.                
  286.                 if(ioIndex==0x03)
  287.                 {
  288.                         target_temperature=target_temperature - 0.1;
  289.                         ioIndex=0x00;
  290.                 }
  291.                
  292.                 if(ioIndex==0x04)
  293.                 {
  294.                         target_temperature=target_temperature + 0.1;
  295.                         ioIndex=0x00;
  296.                 }        

  297.                         if(target_temperature>40.5) target_temperature=37.9;
  298.                         if(target_temperature<32.0) target_temperature=37.8;
  299.    
  300. //计算当前温度               
  301.     adc_ordinary_software_trigger_enable(ADC2, TRUE);
  302.     while(!adc_flag_get(ADC2, ADC_OCCE_FLAG));
  303.     adc_flag_clear(ADC2, ADC_OCCE_FLAG);
  304.     adc_result = adc_ordinary_conversion_data_get(ADC2);
  305.    
  306.                 Rval=(adc_result*6200.0)/(4095.0-adc_result);
  307.     current_temperature = Res_to_Tem(Rval);
  308.     if(current_temperature>= 99.0)  current_temperature =  99.0;
  309.     if(current_temperature<=-30.0) current_temperature  = -30.0;
  310.    
  311.   //简单粗暴,如果温度低于目标温度就加温否则就不加温
  312.         if(current_temperature<target_temperature)
  313.         {
  314.           gpio_bits_set(GPIOA, GPIO_PINS_6);
  315.         }
  316.         else
  317.         {
  318.           gpio_bits_reset(GPIOA, GPIO_PINS_6);
  319.         }
  320.    
  321.     if(flag_s)
  322.                 {
  323.                         flag_s=0;
  324.                         
  325.                         sprintf((char*)target_temperature_string,  "%2.1f",  target_temperature);  // 格式化为保留一位小数的字符串        
  326.                         sprintf((char*)current_temperature_string, "%2.1f", current_temperature);  // 格式化为保留一位小数的字符串
  327.                         sprintf((char*)day_s, "%02d", time_days);
  328.                         sprintf((char*)time_char,"%02d:%02d:%02d",time_hour,time_min,time_s);
  329.                   sprintf((char*)adc_temp, "%04d", adc_ordinary_conversion_data_get(ADC2));
  330.         

  331.                         printf_ASCII_16_text(64+8,2,target_temperature_string);                              //在第2行,显示设置的目标温度数值
  332.                         printf_ASCII_16_text(64+8,4,"     ");
  333.                         printf_ASCII_16_text(64+8,4,current_temperature_string);                             //在第3行,显示当前采集的温度数值
  334.                   printf_ASCII_16_text(64,6,time_char);                                //在第4行,显示“时分秒”
  335.         //                printf_ASCII_16_text(64+16,6,adc_temp);                            //在第4行,显示ADC测试值
  336.                         printf_ASCII_16_text(24,6,day_s);                                //在第4行,显示天数
  337.         //  FillAll(0);
  338.                 }
  339.    
  340.   }
  341. }

  342. void TMR1_OVF_TMR10_IRQHandler(void)
  343. {
  344.   if(tmr_interrupt_flag_get(TMR1, TMR_OVF_FLAG) == SET)
  345.   {
  346.     time_ms++;
  347.     if(time_ms>=1000)
  348.     {
  349.       time_ms=0;
  350.       time_s++;
  351.       flag_s=1;//用于动态刷新,每秒1次
  352.       if(time_s>=60)
  353.       {
  354.         time_s=0;
  355.         time_min++;
  356.         if(time_min>=60)
  357.         {
  358.           time_min=0;
  359.           time_hour++;
  360.           if(time_hour>=24)
  361.           {
  362.             time_hour=0;
  363.             time_days++;
  364.             if(time_days>99) time_days=0;
  365.           }
  366.         }
  367.       }
  368.     }
  369.     tmr_flag_clear(TMR1, TMR_OVF_FLAG);
  370.   }
  371. }





  372. void i2c_lowlevel_init(i2c_handle_type* hi2c)
  373. {
  374.   gpio_init_type gpio_init_structure;
  375.   if(hi2c->i2cx == I2Cx_PORT)
  376.   {
  377.     crm_periph_clock_enable(I2Cx_CLK, TRUE);
  378.     crm_periph_clock_enable(I2Cx_SCL_GPIO_CLK, TRUE);
  379.     crm_periph_clock_enable(I2Cx_SDA_GPIO_CLK, TRUE);
  380.     gpio_pin_mux_config(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_GPIO_PinsSource, I2Cx_SCL_GPIO_MUX);
  381.     gpio_pin_mux_config(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_GPIO_PinsSource, I2Cx_SDA_GPIO_MUX);
  382.     gpio_init_structure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  383.     gpio_init_structure.gpio_mode = GPIO_MODE_MUX;
  384.     gpio_init_structure.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
  385.     gpio_init_structure.gpio_pull = GPIO_PULL_UP;
  386.     gpio_init_structure.gpio_pins = I2Cx_SCL_GPIO_PIN;
  387.     gpio_init(I2Cx_SCL_GPIO_PORT, &gpio_init_structure);
  388.     gpio_init_structure.gpio_pins = I2Cx_SDA_GPIO_PIN;
  389.     gpio_init(I2Cx_SDA_GPIO_PORT, &gpio_init_structure);
  390.     i2c_init(hi2c->i2cx, 0x0F, I2Cx_CLKCTRL);
  391.   }
  392. }
17575684f9fffb7722.jpg

测试视频

https://www.bilibili.com/video/BV1u6MvzHEQR?t=2.4
官方 的库函数有点多,需要配合手册才好理解。另外PWM也非常好用,需要慢慢掌握外设的配置方式和官方的库函数使用方法。


您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2046

主题

16356

帖子

221

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2046

主题

16356

帖子

221

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