解读set_gpio_ctrl(GPIO_MODE_OUT | GPIO_H6)

本文详细解读了 Linux 内核中针对 S3C2410 处理器 GPIO 操作的宏定义及其实现原理。通过对关键宏如 set_gpio_ctrl 的分析,介绍了 GPIO 端口的配置过程,包括设置输入输出模式、上拉电阻等。

做嵌入式底层的东西,初始化硬件设备应该是必须的。一个个内核调用函数足以让人头晕! 
         最近在看Linux嵌入式(s3c2410)方面的内容,遇到了这样一个函数:set_gpio_ctrl(); 它从字面上看来是对gpio口的设置扩展GPIO是什么呢?它是通用 IO端口引脚,在s3c2410用户手册中有A,B,C,D,E,F,G,H7组共117个引脚。这些引脚除了可作为INPUT/OUTPUT外,大部份还可以用作其它用,如外部中断,UART等。它们用的控制寄存器主要有GPACON-GPHCON,GPADAT-GPHDAT,GPBUP- GPHUP,还有一些不累赘了。
       我在linux内核原代码的/include/asm-arm/arch-s3c2410/s3c2410.h 这头文件个找
到set_gpio_ctrl()函数的定义,体质来讲是个宏定义。

#define GPCON(x) __REG2(0x56000000, (x) * 0x10)       //(此为GPACON---GPHCON 的一种表示)
#define GPDAT(x) __REG2(0x56000004, (x) * 0x10)       //(此为GPADAT--GPHDAT 的一种表示)
#define GPUP(x) __REG2(0x56000008, (x) * 0x10)
#define GPIO_OFS_SHIFT  0
#define GPIO_PORT_SHIFTT 8
#define GPIO_PULLUP_SHIFT 16
#define GPIO_MODE_SHIFT  24
#define GPIO_OFS_MASK  0x000000ff
#define GPIO_PORT_MASK  0x0000ff00
#define GPIO_PULLUP_MASK 0x00ff0000
#define GPIO_MODE_MASK  0xff000000
#define GPIO_MODE_IN  (0 << GPIO_MODE_SHIFT)
#define GPIO_MODE_OUT  (1 << GPIO_MODE_SHIFT)
#define GPIO_MODE_ALT0  (2 << GPIO_MODE_SHIFT)
#define GPIO_MODE_ALT1  (3 << GPIO_MODE_SHIFT)
#define GPIO_PULLUP_EN  (0 << GPIO_PULLUP_SHIFT)
#define GPIO_PULLUP_DIS  (1 << GPIO_PULLUP_SHIFT)
#define PORTA_OFS  0
#define PORTB_OFS  1
#define PORTC_OFS  2
#define PORTD_OFS  3
#define PORTE_OFS  4
#define PORTF_OFS  5
#define PORTG_OFS  6
#define PORTH_OFS  7
#define MAKE_GPIO_NUM(p, o) ((p << GPIO_PORT_SHIFTT) | (o << GPIO_OFS_SHIFT))
#define GRAB_MODE(x)  (((x) & GPIO_MODE_MASK) >> GPIO_MODE_SHIFT)
#define GRAB_PULLUP(x)  (((x) & GPIO_PULLUP_MASK) >> GPIO_PULLUP_SHIFT)
#define GRAB_PORT(x)  (((x) & GPIO_PORT_MASK) >> GPIO_PORT_SHIFTT)
#define GRAB_OFS(x)  (((x) & GPIO_OFS_MASK) >> GPIO_OFS_SHIFT)
                                        #set_gpio_ctrl(GPIO_MODE_OUT|GPIO_F6) 设
置相应GPIO位是输入还是输出
#define set_gpio_ctrl(x) /
 ({ GPCON(GRAB_PORT((x))) &= ~(0x3 << (GRAB_OFS((x))*2)); /
    GPCON(GRAB_PORT(x)) |= (GRAB_MODE(x) << (GRAB_OFS((x))*2)); /
    GPUP(GRAB_PORT((x))) &= ~(1 << GRAB_OFS((x))); /
    GPUP(GRAB_PORT((x))) |= (GRAB_PULLUP((x)) << GRAB_OFS((x))); })
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#define set_gpioA_mode(x) /
 ({ GPCON(GRAB_PORT((x))) &= ~(0x1 << GRAB_OFS((x))); /
    GPCON(GRAB_PORT((x))) |= (GRAB_MODE((x)) << GRAB_OFS((x))); })
#define read_gpio_bit(x) ((GPDAT(GRAB_PORT((x))) & (1<<GRAB_OFS((x)))) >>
GRAB_OFS((x)))
#define read_gpio_reg(x) (GPDAT(GRAB_PORT((x)))
#define write_gpio_bit(x, v) /
 ({ GPDAT(GRAB_PORT((x))) &= ~(0x1 << GRAB_OFS((x))); /
    GPDAT(GRAB_PORT((x))) |= ((v) << GRAB_OFS((x))); })
#define write_gpio_reg(x, v) (GPDAT(GRAB_PORT((x))) = (v))
 
#define GPIO_A0    MAKE_GPIO_NUM(PORTA_OFS, 0)
#define GPIO_A1    MAKE_GPIO_NUM(PORTA_OFS, 1)
::::::::::::::::::::
#define GPIO_A21   MAKE_GPIO_NUM(PORTA_OFS, 21)
#define GPIO_A22   MAKE_GPIO_NUM(PORTA_OFS, 22)
#define GPIO_H0    MAKE_GPIO_NUM(PORTH_OFS, 0)
#define GPIO_H6    MAKE_GPIO_NUM(PORTH_OFS, 6)
::::::::::::::::::::
#define GPIO_H10   MAKE_GPIO_NUM(PORTH_OFS, 10)
#define GPIO_MODE_nXBACK  GPIO_MODE_ALT0
:::::::::::::::::::::;;;
#define GPIO_MODE_LCD_PWRDN  GPIO_MODE_ALT1
     第一个要明白的是GPCON(x)。GPACON-GPHCON为端口控制寄存器。其起始地趾为0x56000000
#define GPCON(x) __REG2(0x56000000, (x) * 0x10)       x的取值为0-7对应GPACON---GPHCON 的地址。
#define GPDAT(x) __REG2(0x56000004, (x) * 0x10)        #(此为GPADAT--GPHDAT 的一种表示)
#define GPUP(x) __REG2(0x56000008, (x) * 0x10)         也是一样的道理。
     第二个是 GPIO_OFS_SHIFT  GPIO_PORT_SHIFT  GPIO_PULLUP_SHIFT  GPIO_MODE_SHIFT
。s3c2410.h中是这样定义的:
#define GPIO_OFS_SHIFT          0                                  #define GPIO_OFS_MASK  0x000000ff
#define GPIO_PORT_SHIFTT     8        相对应              #define GPIO_PORT_MASK  0x0000ff00
#define GPIO_PULLUP_SHIFT 16                                  #define GPIO_PULLUP_MASK 0x00ff0000
#define GPIO_MODE_SHIFT      24                                 #define GPIO_MODE_MASK  0xff000000
他们的作用是什么呢,为什么要这样定义呢?我们都知道对硬件的初始化和操作有很大一部分是对其相对应的寄存器的操作。说白一点也就是对相应位置 0或1。s3c2410的寄存器是32位的,再来看一下set_gpio_ctrl(GPIO_MODE_OUT |  GPIO_H6)中的参数:GPIO_MODE_OUT |  GPIO_H6。它表示将端口组H的6端口设置成输出模式(MODE)。看一下参数命令的结构,这很重要,是突破点:这命令化成数值是32位的,高位为GPIO_MODE_OUT, 低位为GPIO_H6。那么GPIO_MODE_OUT和GPIO_H6又是什么呢,再看几个定义:
#define GPIO_MODE_IN       (0 << GPIO_MODE_SHIFT)
#define GPIO_MODE_OUT   (1 << GPIO_MODE_SHIFT)
#define GPIO_MODE_ALT0  (2 << GPIO_MODE_SHIFT)
#define GPIO_MODE_ALT1  (3 << GPIO_MODE_SHIFT)
#define GPIO_PULLUP_EN  (0 << GPIO_PULLUP_SHIFT)
#define GPIO_PULLUP_DIS  (1 << GPIO_PULLUP_SHIFT) 
###MODE_IN,MODE_OUT,MODE_  是表示端口的作用是输入输出还是另作它用。
#为什么要用0,1来左移呢?s3c2410数据手册告诉我们00表示输入01表示输出
#GPIO_MODE_SHIFT=24即把00或01搬到第24位去:  1  0000 0000 0000 0000 0000 0000
##或 0  0000 0000 0000 0000 0000 0000(这是用32位中的位24-31来表示端口的作用)
##那么命令中的GPIO_H6:即哪个端口组的哪个端口又是如何表示的?看看下面的
#define GPIO_OFS_SHIFT  0 
#define GPIO_PORT_SHIFTT 8       
#define GPIO_PULLUP_SHIFT 16
#define PORTA_OFS  0 ##和#define GPIO_MODE_SHIFT  24  看看,我们大致可以猜到:(这是这是用32位中的位16-23来表示要设置某个端口的上拉功能)
#define PORTB_OFS  1 ##(这是用32位中的位8-15来表示要设置哪一个端口组)
#define PORTC_OFS  2  ###(这是用32位中的位0-7来表示要设置一个端口组的哪一个端口)
#define PORTD_OFS  3  #那么类似GPIO_H6是如何构造的?看下面的宏定义,我们展开:
#define PORTE_OFS  4 #GPIO_H6=MAKE_GPIO_NUM(7, 6)
#define PORTF_OFS  5 #= ( (7<<8) | (6<<0))= ( 111 0000 0000  |  110)=111 0000 110
  
#define PORTG_OFS  6#看出程序把端口组A-H用0-7表示放在8-15位
#define PORTH_OFS  7##端口组中具体端口则放在0-7位

 

#MAKE_GPIO_NUM(p, o)这个宏就是构造这样的
#define MAKE_GPIO_NUM(p, o) ((p << GPIO_PORT_SHIFTT) | (o << GPIO_OFS_SHIFT))
#define GPIO_H6    MAKE_GPIO_NUM(PORTH_OFS, 6)
       前面分析了参数命令的构造,那么如何解释命令呢?
#define GRAB_MODE(x)  (((x) & GPIO_MODE_MASK) >> GPIO_MODE_SHIFT)
#define GRAB_PULLUP(x)  (((x) & GPIO_PULLUP_MASK) >> GPIO_PULLUP_SHIFT)
#define GRAB_PORT(x)  (((x) & GPIO_PORT_MASK) >> GPIO_PORT_SHIFTT)
#define GRAB_OFS(x)  (((x) & GPIO_OFS_MASK) >> GPIO_OFS_SHIFT)
grab顾名思义,是抓取的意思。GRAB_MODE(x)是把命令的端口模式取出,得到的是一8位的值。GRAB_PORT(x)得到端口组,GRAB_OFS(x)得到端口号。
        最重要的已经分析完了,在回过头来看一下set_gpio_ctrl()
 #define set_gpio_ctrl(x) /
 ({ GPCON(GRAB_PORT((x))) &= ~(0x3 << (GRAB_OFS((x))*2)); /
    GPCON(GRAB_PORT(x)) |= (GRAB_MODE(x) << (GRAB_OFS((x))*2)); /
    GPUP(GRAB_PORT((x))) &= ~(1 << GRAB_OFS((x))); /
    GPUP(GRAB_PORT((x))) |= (GRAB_PULLUP((x)) << GRAB_OFS((x))); })       
 GPCON(GRAB_PORT((x)))   表示一个端口组的控制寄存器.
在控制寄存器里是用2位来表示去功能:0-1表示0端口,2-3表示1端口;;;;;
所以GRAB_OFS((x))*2 表示这个端口号是从寄存器的第几位开始.
GPCON(GRAB_PORT((x))) &= ~(0x3 << (GRAB_OFS((x))*2)); 表示把对应位清0.
以下类似,不一一表书.

一、GPIO寄存器定义

1
#define GPCON(x) __REG2(0x56000000, (x) * 0x10)

  这句是定义2410GPIO的控制寄存器,注意:__REG2的参数是寄存器的物理地址,这个物理地址经_REG2宏转换为虚拟地址,对照2410的手册可以得到一下对应关系:

GPCON
1 ------ PORT A 0x56000000
GPCON
2 ------ PORT B 0x56000010
GPCON
3 ------ PORT C 0x56000020
……
GPCON
8 ------ PORT H 0x56000070

2
#define GPDAT(x) __REG2(0x56000004, (x) * 0x10)

 这句是定义2410GPIO的数据寄存器,定义方法同GPCON宏。

GPDAT
1 ------ PORT A 0x56000004
GPDAT
2 ------ PORT B 0x56000014
GPDAT
3 ------ PORT C 0x56000024
……
GPDAT
8 ------ PORT H 0x56000074

3
#define GPUP(x) __REG2(0x56000008, (x) * 0x10)

  这句是定义2410GPIO的上拉电阻屏蔽/激活寄存器,定义方法同GPCON宏。
GPUP
1 ------ PORT A 0x56000008
GPUP
2 ------ PORT B 0x56000018
GPUP
3 ------ PORT C 0x56000028
……
GPUP
8 ------ PORT H 0x56000078

二、GPIO端口号定义
  以GPIO_G12来说明在内核头文件$(KERNEL_INCLUDE)/asm-arm/arch/s3c2410.h中是如何来定义IO port的端口号的。定义GPIO端口主要涉及到以下几个宏:

  #define MAKE_GPIO_NUM(p, o) ( (p << GPIO_PORT_SHIFTT) | (o << GPIO_OFS_SHIFT))
  #define GPIO_G12 MAKE_GPIO_NUM(PORTG_OFS, 12)

GPIO_PORT_SHIFTT
值为8,代表GPIO组号在整个GPIO端口号(如GPIO_G12)字段中的位移
GPIO_OFS_SHIFT
值为0,代表GPIO组内偏移号在整个GPIO端口号(如GPIO_G12)字段中的位移

s3c2410
117个多功能input/output port pins。分为以下八组:

Port A (GPA): 23-output port #define PORTA_OFS 0
Port B (GPB): 11-input/output port #define PORTB_OFS 1
Port C (GPC): 16-input/output port #define PORTC_OFS 2
Port D (GPD): 16-input/output port #define PORTD_OFS 3
Port E (GPE): 16-input/output port #define PORTE_OFS 4
Port F (GPF): 8-input/output port #define PORTF_OFS 5
Port G (GPG): 16-input/output port #define PORTG_OFS 6
Port H (GPH): 11-input/output port #define PORTH_OFS 7

  GPG12属于G组,组内偏移为12,从上述两个宏定义中,我们可以很清楚地看出GPIO_G12结构:
         
                           图1 GPIO端口号结构图
  端口一共有8组,从上面的宏定义可以看出,端口组号p的范围:07。而组内偏移各组不尽相同,Port A23个输出口,因此它的组内偏移o022Port G16IO口,它的组内偏移o015,其他组的GPIO以此类推。

三、write_gpio_bit(x,v)宏分析
  write_gpio_bit宏传入两个参数,第一个为GPIO端口号,如GPIO_G12;第二个参数为10,为相应IO口设置高电平或低电平输出。具体宏展开如下:
代码
#define write_gpio_bit(x, v)
({
GPDAT(GRAB_PORT((x))) &= ~(0x1 << GRAB_OFS((x)));
GPDAT(GRAB_PORT((x))) |= ((v) << GRAB_OFS((x)));
})


GRAB_PORT
宏的参数是GPIO端口号,功能是从GPIO端口号中解析出组号,具体定义如下:

#define GRAB_PORT(x) (((x) & GPIO_PORT_MASK) >> GPIO_PORT_SHIFTT)

其中GPIO_PORT_MASK是组号的掩码,值为0x0000ff00,从图1中也可看出。

GRAB_OFS
宏和GRAB_PORT类似,它的功能是从GPIO端口号中解析出组内偏移:

#define GRAB_OFS(x) (((x) & GPIO_OFS_MASK) >> GPIO_OFS_SHIFT)

其中偏移值掩码GPIO_OFS_MASK0x000000ff

  现在我们结合上述说明来分析write_gpio_bit(GPIO_G12,1)这条语句:由GPIO_G12的宏定义可计算出其值为0x0000060CGRAB_PORTGPIO_G12)解析得到所操作的IO属于G组,组号为6GRAB_OFSGPIO_G12)解析得到此IO口为G组的第12个引脚(从0开始算起),为GPG12,表达式值为12。则write_gpio_bit(GPIO_G12,1)等价于下面两条语句:

GPDAT(6) &= ~(0x1<<12); //GPGDAT
寄存器第12位清零
GPDAT(6) | = 1<<12; //
GPGDAT寄存器第12位写入‘1

  到此,我们知道了write_gpio_bit(GPIO_G12,1)这条语句是将GPG12这个引脚拉成高电平。

  四、set_gpio_ctrl(x)宏分析完成了对write_gpio_bit宏的分析,现在来看set_gpio_ctrl就很简单了!在它的宏展开中只多了GRAB_MODE(x) GRAB_PULLUP(x)分别表示从参数x中解析出IO口的模式和使能/屏蔽此端口的上拉电阻。值得注意的是set_gpio_ctrl的参数x不仅仅表示GPIO端口号,其高16位还带有模式状态和上拉电阻控制信息,参数x的结构如下图:
      
                     图2 set_gpio_ctrl的参数字段结构图
  低16位即为前面所述的GPIO的端口号,高16位中的R字段用来屏蔽/使能IO口的上拉电阻功能。R0,上拉电阻使能;R1,上拉电阻失效。M字段用来设置IO口的工作模式,M0IO口为输入端口;M1IO口为输出端口;M2,可选功能1M3,可选功能2

  set_gpio_ctrl宏就是通过写相应GPIO所在组的GPXCONXAH)的相应位来设置IO口模式(GPACON每一个位控制一个IO口,而GPBCONGPHCON都是两个位控制一个IO口的模式),通过写GPXUPXAH)来决定是否启用上拉电阻。典型的set_gpio_ctrl调用方式如下:

  set_gpio_ctrl(GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G12);

代码
#define set_gpio_ctrl(x)
({ GPCON(GRAB_PORT((x))) &= ~(0x3 << (GRAB_OFS((x))*2));
GPCON(GRAB_PORT(x)) |= (GRAB_MODE(x) << (GRAB_OFS((x))*2));
GPUP(GRAB_PORT((x))) &= ~(1 << GRAB_OFS((x)));
GPUP(GRAB_PORT((x))) |= (GRAB_PULLUP((x)) << GRAB_OFS((x))); })



  这条语句是将GPG12设置成输出模式,并且不使用端口的上拉电阻。

五、结束
  以上主要结合《S3C2410X 32-BIT RISC MICROPROCESSOR USER'S MANUAL》分析了$(LINUX_KERNEL_INCLUDE)/asm-arm/arch/s3c2410.h中所定义的对2410GPIO进行操作的几个宏,除了文中提及的几个宏,除此还有read_gpio_bit(x)read_gpio_reg(x) write_gpio_reg(x, v)等,实现方法和上述类似,在此不再一一赘述

#include "stm32f10x.h" // ???? void Timer4_Init(u16 Period); void led_init(void); void key_init(void); void delay_init(void); void delay_us(u32 nus); void delay_ms(u16 nms); uint8_t KEY_Scan(uint8_t mode); void play_music(void); void change_song(int direction); void show_song_info(void); // ?????? static u8 fac_us = 0; // us????? static u16 fac_ms = 0; // ms????? // ???? #define proport 10000 // Tclk/(psc+1)=72000000/(7199+1) #define L1 ((proport/131)-1) // ?? do ?? #define L2 ((proport/147)-1) // ?? re ?? #define L3 ((proport/165)-1) // ?? mi ?? #define L4 ((proport/176)-1) // ?? fa ?? #define L5 ((proport/196)-1) // ?? sol ?? #define L6 ((proport/220)-1) // ?? la ?? #define L7 ((proport/247)-1) // ?? si ?? #define M1 ((proport/262)-1) // ?? do ?? #define M2 ((proport/296)-1) // ?? re ?? #define M3 ((proport/330)-1) // ?? mi ?? #define M4 ((proport/349)-1) // ?? fa ?? #define M5 ((proport/392)-1) // ?? sol ?? #define M6 ((proport/440)-1) // ?? la ?? #define M7 ((proport/494)-1) // ?? si ?? #define H1 ((proport/523)-1) // ?? do ?? #define H2 ((proport/587)-1) // ?? re ?? #define H3 ((proport/659)-1) // ?? mi ?? #define H4 ((proport/699)-1) // ?? fa ?? #define H5 ((proport/784)-1) // ?? sol ?? #define H6 ((proport/880)-1) // ?? la ?? #define H7 ((proport/988)-1) // ?? si ?? // ???? #define KEY0 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3) // K0??:PA3 #define KEY1 GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) // K1??:PC4 // ???? const int music1[] = // ???? { M5, 50, M5, 25, M5, 25, M6, 100, M5, 100, H1, 100, M7, 100, M7, 100, M5, 50, M5, 25, M5, 25, M6, 100, M5, 100, H2, 100, H1, 100, H1, 100, M5, 50, M5, 25, M5, 25, H5, 100, H3, 100, H1, 100, M7, 100, M6, 100, H4, 50, H4, 25, H4, 25, H3, 100, H1, 100, H2, 100, H1, 100, H1, 100 }; const int music2[] = // ???? { M1, 100, M2, 100, M3, 100, M1, 100, M1, 100, M2, 100, M3, 100, M1, 100, M3, 100, M4, 100, M5, 200, M3, 100, M4, 100, M5, 200, M5, 50, M6, 50, M5, 50, M4, 50, M3, 100, M1, 100, M5, 50, M6, 50, M5, 50, M4, 50, M3, 100, M1, 100, M1, 100, M5, 100, M1, 200, M1, 100, M5, 100, M1, 200 }; const int music3[] = // ??? { M1, 100, M1, 100, M5, 100, M5, 100, M6, 100, M6, 100, M5, 200, M4, 100, M4, 100, M3, 100, M3, 100, M2, 100, M2, 100, M1, 200, M5, 100, M5, 100, M4, 100, M4, 100, M3, 100, M3, 100, M2, 200, M5, 100, M5, 100, M4, 100, M4, 100, M3, 100, M3, 100, M2, 200, M1, 100, M1, 100, M5, 100, M5, 100, M6, 100, M6, 100, M5, 200, M4, 100, M4, 100, M3, 100, M3, 100, M2, 100, M2, 100, M1, 200 }; // ??????????? const int* music_list[] = {music1, music2, music3}; const int music_length[] = {sizeof(music1)/sizeof(music1[0]), sizeof(music2)/sizeof(music2[0]), sizeof(music3)/sizeof(music3[0])}; const char* music_names[] = {"????", "????", "???"}; int current_music = 0; // ???????? int music_count = 3; // ???? // ?????? volatile uint8_t music_playing = 0; // ?????? volatile uint8_t song_changed = 0; // ??????? uint8_t is_paused = 0; // ???? int main() { delay_init(); // ??????? led_init(); // ???LED key_init(); // ????? show_song_info(); // ???????? while (1) { // ??????? uint8_t key = KEY_Scan(0); if (key == 1) { // K0??,??? change_song(1); } else if (key == 2) { // K1??,??? change_song(-1); } // ??????:K0?K1???? if (KEY0 == 0 && KEY1 == 0) { delay_ms(50); // ?? if (KEY0 == 0 && KEY1 == 0) { is_paused = !is_paused; if (is_paused) { Timer4_Init(0); // ???? } else { // ????????? music_playing = 0; } while(KEY0 == 0 && KEY1 == 0); // ?????? } } // ????(????) if (!is_paused && !music_playing && !song_changed) { play_music(); } // ?????? if (song_changed) { song_changed = 0; show_song_info(); } } } // ????????? void play_music(void) { const int* music = music_list[current_music]; int length = music_length[current_music]; int i; music_playing = 1; for (i = 0; i < (length / 2); i++) { // ????????????? if (song_changed || is_paused) { Timer4_Init(0); // ???? music_playing = 0; return; } Timer4_Init(music[2 * i]); // ??PWM??(??) delay_ms(5 * music[2 * i + 1]); // ?????? // ??????? Timer4_Init(0); delay_ms(20); } delay_ms(1000); // ????????? music_playing = 0; } // ???? void change_song(int direction) { // ??????,??? if (music_playing) { song_changed = 1; // ???????? while(music_playing); } // ????????? current_music += direction; if (current_music >= music_count) current_music = 0; if (current_music < 0) current_music = music_count - 1; // ???????? Timer4_Init(H1); delay_ms(200); Timer4_Init(0); song_changed = 1; } // ????????(??LED??) void show_song_info(void) { int i; // ????LED GPIO_SetBits(GPIOB, GPIO_Pin_5); GPIO_SetBits(GPIOE, GPIO_Pin_5); // ??????(3?) for (i = 0; i < 3; i++) { GPIO_ResetBits(GPIOB, GPIO_Pin_5); delay_ms(150); GPIO_SetBits(GPIOB, GPIO_Pin_5); delay_ms(100); } delay_ms(300); // ???????? for (i = 0; i < current_music + 1; i++) { GPIO_ResetBits(GPIOB, GPIO_Pin_5); delay_ms(200); GPIO_SetBits(GPIOB, GPIO_Pin_5); delay_ms(150); } delay_ms(500); // ????????(??LED????) if (current_music == 0) { // ???? for (i = 0; i < 3; i++) { // PB5??3? GPIO_ResetBits(GPIOB, GPIO_Pin_5); delay_ms(100); GPIO_SetBits(GPIOB, GPIO_Pin_5); delay_ms(100); } delay_ms(200); for (i = 0; i < 2; i++) { // PE5??2? GPIO_ResetBits(GPIOE, GPIO_Pin_5); delay_ms(200); GPIO_SetBits(GPIOE, GPIO_Pin_5); delay_ms(200); } } else if (current_music == 1) { // ???? for (i = 0; i < 2; i++) { // PB5??2? GPIO_ResetBits(GPIOB, GPIO_Pin_5); delay_ms(100); GPIO_SetBits(GPIOB, GPIO_Pin_5); delay_ms(100); } delay_ms(200); for (i = 0; i < 2; i++) { // PE5??2? GPIO_ResetBits(GPIOE, GPIO_Pin_5); delay_ms(100); GPIO_SetBits(GPIOE, GPIO_Pin_5); delay_ms(100); } } else { // ??? for (i = 0; i < 3; i++) { // PB5??3? GPIO_ResetBits(GPIOB, GPIO_Pin_5); delay_ms(200); GPIO_SetBits(GPIOB, GPIO_Pin_5); delay_ms(200); } } delay_ms(1000); } // ???4???,??PWM??(???????) void Timer4_Init(u16 Period) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCStructure; // ?????????(???0) if (Period == 0) { TIM_Cmd(TIM4, DISABLE); // ????? return; } RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); // ??TIM4?? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // ??GPIOB?? // ??PB8???????(TIM4_CH3) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // ??TIM4?? TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // ?????? TIM_TimeBaseStructure.TIM_Period = Period; // ??????(????) TIM_TimeBaseStructure.TIM_Prescaler = 7199; // ????(72MHz/7200=10kHz) TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); // ??PWM?? TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM2; // PWM??2 TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_High; // ????? TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable; // ???? TIM_OCStructure.TIM_Pulse = Period / 2; // ????50%(???) TIM_OC3Init(TIM4, &TIM_OCStructure); TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable); // ???????? TIM_Cmd(TIM4, ENABLE); // ????? } // LED????? void led_init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE); // ??PB5????? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // ??PE5????? GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_Init(GPIOE, &GPIO_InitStructure); // ????LED?? GPIO_SetBits(GPIOB, GPIO_Pin_5); GPIO_SetBits(GPIOE, GPIO_Pin_5); } // ????? void key_init(void) { GPIO_InitTypeDef GPIO_InitStructure; // ??GPIOA?GPIOC?? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE); // ??PA3?????(K0??) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // ??PC4?????(K1??) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_Init(GPIOC, &GPIO_InitStructure); } // ?????? uint8_t KEY_Scan(uint8_t mode) { static uint8_t key_up = 1; // ?????? if (mode) key_up = 1; // ???? if (key_up && (KEY0 == 0 || KEY1 == 0)) { delay_ms(15); // ???????15ms key_up = 0; if (KEY0 == 0) return 1; // K0?? if (KEY1 == 0) return 2; // K1?? } else if (KEY0 == 1 && KEY1 == 1) { key_up = 1; } return 0; // ????? } // ??????? void delay_init(void) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); // ??SysTick???HCLK/8 fac_us = SystemCoreClock / 8000000; // 72MHz??????9 fac_ms = (u16)fac_us * 1000; // 9000,1ms??9000?SysTick?? } // ??????? void delay_us(u32 nus) { u32 temp; SysTick->LOAD = nus * fac_us; // ???????? SysTick->VAL = 0x00; // ????? SysTick->CTRL |= SysTick_CTRL_ENABLE; // ????? do { temp = SysTick->CTRL; } while ((temp & 0x01) && !(temp & (1 << 16))); // ?????? SysTick->CTRL &= ~SysTick_CTRL_ENABLE; // ????? SysTick->VAL = 0X00; // ????? } // ??????? void delay_ms(u16 nms) { u32 temp; SysTick->LOAD = (u32)nms * fac_ms; // ???????? SysTick->VAL = 0x00; // ????? SysTick->CTRL |= SysTick_CTRL_ENABLE; // ????? do { temp = SysTick->CTRL; } while ((temp & 0x01) && !(temp & (1 << 16))); // ?????? SysTick->CTRL &= ~SysTick_CTRL_ENABLE; // ????? SysTick->VAL = 0X00; // ????? }
06-20
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2022 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "delay.h" #include "at24c04.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ //typedef uint32_t u32; //typedef uint16_t u16; //typedef uint8_t u8; //typedef const uint8_t uc8; // //#ifndef __cplusplus //typedef enum {FALSE = 0, TRUE = !FALSE} bool; //#endif #define WorkLED_off HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9,GPIO_PIN_SET); #define WorkLED_on HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9,GPIO_PIN_RESET); /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* 1 H2 2 O2 3 C2H4O 4 CO 5 H2S 6 SO2 7 CL2 负增长 8 HCL 9 HCN 10 NO 11 PH3 12 NO2 13 CLO2 14 NH3 15 EX 16 CH4 17 CO2 18 SF6 19 HF 20 C2H3CL 21 C6H6 22 CH3OH 23 CH2O 24 VOC 25 CHCIF2 26 丙酮 27 甲苯 28 异丁烯 29 异丁烷 30 乙炔 31 丙烷 32 天然气 33 毒油漆稀料 34 氩气 35 毒三乙胺 36 可燃三乙胺 37 可燃油漆稀料 */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ ADC_HandleTypeDef hadc1; DMA_HandleTypeDef hdma_adc1; TIM_HandleTypeDef htim3; UART_HandleTypeDef huart4; /* USER CODE BEGIN PV */ /****************************************************************************/ u16 DEC_meas; u16 set_ZERO; u16 set_FULL; u16 DEC_1_alarm; u16 DEC_2_alarm; u16 DEC_3_alarm; u16 sensor_baud; u16 o2_cail_low_value; u16 o2_cail_high_value; u16 o2_disp_low_value; u16 o2_disp_high_value; u16 twa; u16 stel; u8 gas_point; u8 gas_unit; u8 gas_type; u8 O2_cail_switch; u8 gas_disp_zero_value; u8 sensor_add; u8 O2_cail_value_time; u8 wait_init_time; u8 Temperature_List[100]; /****************************************************************************/ /****************************************************************************/ u16 PPM; u8 current_status; u16 range; u8 uart_work_flag=0; //========ADC================ u16 adc_buf[512]; u16 Gas_adc_value; u16 Pi; //========Temperature======== u8 temperature_error_flag; u8 ofter_temp; u8 cur_temp; u8 temperature_count; u16 send_temp; //=0xffff,is fault;1000=0,1001=1,999=-1 //========USART4============== u8 Rx4[1]; u8 uart4_rx_buf[300]; u8 uart4_temp_buf[300]; u8 uart4_rx_count; u16 Modbus_add_reg[300]; u8 uart4_rx_ok_flag=0; u8 h; u8 Modbus_tx_buf[300]; u16 CRC_temp; u32 temp_u32; u32 add_adc; u32 ppm_add; u32 AD_add; u16 ppm_buf[30]; u32 ppm_add,temp_up; u8 ppm_count,a; u8 reg_add; u8 reg_count; u16 main_count; u16 dog_count; u16 led_count; u8 o2_cail_count_flag=0; u16 o2_cail_count; u16 ppm_bb; u16 ppm_b; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_TIM3_Init(void); static void MX_ADC1_Init(void); static void MX_USART4_UART_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ u16 CRC16_creat_TX(u8 *Pushdata, u16 length)//crc=7639*crc1*crc2 { u16 Reg_CRC; u8 RR,i; u8 crc1=0,crc2=0; for(i=0;i<(length);i++) { RR=*Pushdata++; if((i%2)==0)//0,2,4,6,8,10,12,14,16... { crc1+=RR; } crc2+=RR; } Reg_CRC=crc2; Reg_CRC*=crc1; Reg_CRC*=7639; return Reg_CRC; } u8 CRC16_creat_RX(u8 *Pushdata, u16 length) //crc=7639*crc1*crc2 { u16 Reg_CRC,T16; u8 RR,i; u8 crc1=0,crc2=0; for(i=0;i<(length-2);i++) { RR=*Pushdata++; if((i%2)==0)//0,2,4,6,8,10,12,14,16... { crc1+=RR; } crc2+=RR; } T16=*Pushdata++; T16<<=8; T16+=*Pushdata; Reg_CRC=crc2; Reg_CRC*=crc1; Reg_CRC*=7639; if(Reg_CRC==T16) return 1; else return 0; } void init_value(u8 gas_type_u8) { gas_type = gas_type_u8; sensor_add = 1; sensor_baud = 19200; wait_init_time = 30; gas_disp_zero_value = 5; switch(gas_type_u8) { case 0://--------------CO set_ZERO = 200; set_FULL = 3800; DEC_meas = 1000; DEC_1_alarm = 24; DEC_2_alarm = 100; gas_point = 0; gas_unit = 0; gas_type = 4; gas_disp_zero_value = 15; break; case 1://--------------H2 set_ZERO = 200; set_FULL = 3800; DEC_meas = 100; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 0; gas_disp_zero_value = 15; break; case 2://--------------O2 set_ZERO = 0; set_FULL = 3000; DEC_meas = 300; DEC_1_alarm = 195; DEC_2_alarm = 225; gas_point = 1; gas_unit = 2; gas_disp_zero_value = 15; o2_cail_low_value = 100; o2_cail_high_value = 260; o2_disp_low_value = 204; o2_disp_high_value = 214; O2_cail_switch = 0; O2_cail_value_time = 12; wait_init_time = 60; break; case 3://--------------C2H4O set_ZERO = 200; set_FULL = 2525; DEC_meas = 100; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 4://--------------CO set_ZERO = 200; set_FULL = 2125; DEC_meas = 2000; DEC_1_alarm = 24; DEC_2_alarm = 100; gas_point = 0; gas_unit = 0; gas_disp_zero_value = 15; break; case 5://--------------H2S set_ZERO = 200; set_FULL = 2525; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 6://--------------SO2 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 7://--------------CL2 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 8://--------------HCL set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 9://--------------HCN set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 10://--------------NO set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 11://--------------PH3 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 12://--------------NO2 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 13://--------------CLO2 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 14://--------------NH3 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 15://--------------EX set_ZERO = 200; set_FULL = 3800; DEC_meas = 100; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 1; break; case 16://--------------CH4 set_ZERO = 200; set_FULL = 3800; DEC_meas = 100; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 1; break; case 17://--------------CO2 set_ZERO = 200; set_FULL = 3800; DEC_meas = 500; DEC_1_alarm = 100; DEC_2_alarm = 200; gas_point = 2; gas_unit = 2; break; case 18://--------------SF6 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 19://--------------HF set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 20://--------------C2H3CL set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 21://--------------C6H6 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; wait_init_time = 90; break; case 22://--------------CH3OH set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 23://--------------CH20 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 24://--------------VOC set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 25://--------------CHCIF2 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 26://--------------丙酮 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 27://--------------甲苯 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 28://--------------异丁烯 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 29://--------------异丁烷 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 1; break; case 30://--------------乙炔 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 1; break; case 31://--------------丙烷 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 1; break; case 32://--------------天然气 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 1; break; case 33://--------------毒油漆稀料 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 34://--------------氩气 set_ZERO = 200; set_FULL = 3800; DEC_meas = 200; DEC_1_alarm = 10; DEC_2_alarm = 20; gas_point = 0; gas_unit = 0; break; case 35://--------------毒三乙胺 set_ZERO = 200; set_FULL = 3800; DEC_meas = 100; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 0; break; case 36://--------------可燃三乙胺 set_ZERO = 200; set_FULL = 3800; DEC_meas = 100; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 1; break; case 37://--------------可燃油漆稀料 set_ZERO = 200; set_FULL = 3800; DEC_meas = 100; DEC_1_alarm = 25; DEC_2_alarm = 50; gas_point = 0; gas_unit = 1; break; default://--------------CO set_ZERO = 200; set_FULL = 2525; DEC_meas = 2000; DEC_1_alarm = 24; DEC_2_alarm = 100; gas_point = 0; gas_unit = 0; gas_type = 4; gas_disp_zero_value = 15; break; } DEC_3_alarm = DEC_meas; } void PPM_process(u16 value) { u32 tp32; //mmmmmmmmmmmmmmmmm ppm_bb=PPM; if(value<(set_ZERO/3))//fault zer0 { ppm_add=0;for(a=0;a<10;a++)ppm_buf[a]=0; PPM=0; current_status=1; } else if(value<(set_ZERO)) { PPM = 0; ppm_buf[ppm_count++]=PPM; if(ppm_count>=10)ppm_count=0; ppm_add=0;for(a=0;a<10;a++)ppm_add+=ppm_buf[a];ppm_add=ppm_add/10; PPM=(u16)ppm_add; } else if(value<=set_FULL) { tp32 = value-set_ZERO; tp32 = tp32*DEC_meas; tp32 = tp32/range; if(gas_type==2)//o2 { if((tp32>o2_disp_low_value)&&(tp32<o2_disp_high_value)) tp32=209; if(tp32<gas_disp_zero_value) tp32=0; } else { if(gas_type==4)tp32=tp32*Temperature_List[ofter_temp]/100; if(tp32<gas_disp_zero_value) tp32=0; } PPM=(u16)tp32; ppm_buf[ppm_count++]=PPM; if(ppm_count>=10)ppm_count=0; ppm_add=0;for(a=0;a<10;a++)ppm_add+=ppm_buf[a];ppm_add=ppm_add/10; PPM=(u16)ppm_add; } else { PPM=DEC_meas; ppm_buf[ppm_count++]=PPM; if(ppm_count>=10)ppm_count=0; ppm_add=0;for(a=0;a<10;a++)ppm_add+=ppm_buf[a];ppm_add=ppm_add/10; PPM=(u16)ppm_add; } if(PPM==ppm_bb)o2_cail_count_flag=1; else { o2_cail_count=0; o2_cail_count_flag=0; } //mmmmmmmmmmmmmmmmmmmmm generate status 0=normal,1=fault,2,3,4,5overflow if(gas_type==2)//o2 { if(PPM<=DEC_1_alarm){current_status = 2;} else if(PPM<DEC_2_alarm){current_status = 0;} else if(PPM<DEC_meas){current_status = 3;} else {current_status = 5;} } else { if(PPM<DEC_1_alarm){current_status = 0;} else if(PPM<DEC_2_alarm){current_status = 2;} else if(PPM<DEC_3_alarm){current_status = 3;} else if(PPM<=DEC_meas){current_status = 4;} else {current_status = 5;} } Modbus_add_reg[1] = PPM; Modbus_add_reg[6] = current_status; } void RS485_updata(void) { u8 i; Modbus_add_reg[0] = 0; Modbus_add_reg[1] = PPM; Modbus_add_reg[2] = DEC_1_alarm; Modbus_add_reg[3] = DEC_2_alarm; Modbus_add_reg[4] = DEC_3_alarm; Modbus_add_reg[5] = DEC_meas; Modbus_add_reg[6] = current_status; Modbus_add_reg[7] = gas_point; Modbus_add_reg[8] = gas_type; Modbus_add_reg[9] = gas_unit; Modbus_add_reg[10] = send_temp; Modbus_add_reg[11] = Gas_adc_value; Modbus_add_reg[12] = set_ZERO; Modbus_add_reg[13] = set_FULL; Modbus_add_reg[14] = stel; Modbus_add_reg[15] = twa; Modbus_add_reg[16] = 0; Modbus_add_reg[17] = 0; Modbus_add_reg[18] = 0; Modbus_add_reg[19] = 0; Modbus_add_reg[20] = 0; Modbus_add_reg[21] = 0; Modbus_add_reg[22] = 0; Modbus_add_reg[23] = 0; Modbus_add_reg[24] = gas_disp_zero_value; Modbus_add_reg[25] = 0; Modbus_add_reg[26] = 0; Modbus_add_reg[27] = O2_cail_switch; Modbus_add_reg[28] = 0; Modbus_add_reg[29] = 0; Modbus_add_reg[30] = 0; Modbus_add_reg[31] = 0; Modbus_add_reg[32] = 0; Modbus_add_reg[33] = sensor_baud; Modbus_add_reg[34] = sensor_add; Modbus_add_reg[35] = o2_cail_low_value; Modbus_add_reg[36] = o2_cail_high_value; Modbus_add_reg[37] = o2_disp_low_value; Modbus_add_reg[38] = o2_disp_high_value; Modbus_add_reg[39] = O2_cail_value_time; Modbus_add_reg[40] = wait_init_time; for(i=0;i<100;i++)Modbus_add_reg[50+i]=Temperature_List[i]; } void RS485_reg_updata_and_return_ok(u8 add_8) { u16 RR_TEMP; RS485_updata(); uart4_rx_count=0; Modbus_tx_buf[0]=sensor_add; Modbus_tx_buf[1]=0xBB; Modbus_tx_buf[2]=0x06; Modbus_tx_buf[3]=2; RR_TEMP = I2C_readword_24c_x(add_8); Modbus_tx_buf[4]=RR_TEMP>>8; Modbus_tx_buf[5]=RR_TEMP&0XFF; CRC_temp=CRC16_creat_TX(Modbus_tx_buf,6); Modbus_tx_buf[6]=CRC_temp>>8; Modbus_tx_buf[7]=CRC_temp&0xff; HAL_UART_Transmit(&huart4, Modbus_tx_buf,8,60000); } void Send_error_status(u8 stat) { Modbus_tx_buf[0]='S'; Modbus_tx_buf[1]='N'; Modbus_tx_buf[2]='G'; Modbus_tx_buf[3]=stat/10+0x30; Modbus_tx_buf[4]=stat%10+0x30; HAL_UART_Transmit(&huart4, Modbus_tx_buf,5,60000); } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ u16 i,R_TEMP; u32 temp_up; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_TIM3_Init(); MX_ADC1_Init(); MX_USART4_UART_Init(); /* USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ for(i=0;i<5;i++) { WorkLED_on; Delay_Ms(20); WorkLED_off; Delay_Ms(100); } Delay_Ms(1000); gas_type =(u8)I2C_readword_24c_x(0x18); init_value(gas_type); if(!E2PROM_INIT()) { WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WRITE_memory_init_value(); Send_error_status(1);//SNG01 } E2PROM_INIT(); range = set_FULL-set_ZERO; //if(Write_TCN75()!=1) { temperature_error_flag=1; ofter_temp=64; cur_temp=25; send_temp=0xffff; Send_error_status(2);//SNG02 } //else { temperature_error_flag=0; Read_TCN75(); } Delay_Ms(1000); adc_buf[2]=655; HAL_TIM_Base_Start_IT(&htim3); HAL_ADCEx_Calibration_Start(&hadc1); HAL_ADC_Start_DMA(&hadc1,(uint32_t *)(&adc_buf),512); RS485_updata(); Send_error_status(6);//SNG06 led_count=0; uart_work_flag=1; if(gas_type==2) { for(i=0;i<20;i++){PPM_process(Gas_adc_value);Delay_Ms(1000);} if((PPM<o2_cail_high_value)&&(PPM>o2_cail_low_value)) { temp_up=Gas_adc_value-set_ZERO; temp_up=temp_up*DEC_meas; temp_up=temp_up/209; temp_up=temp_up+set_ZERO; set_FULL=(u16)temp_up; for(a=0;a<30;a++)ppm_buf[a]=209; I2C_writteword_24c_x(0x06,set_FULL); range = set_FULL-set_ZERO; } } cur_temp=25; if(temperature_error_flag==0)Read_TCN75(); while (1) { //1 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm cpu status display if(led_count>5) //5=500ms { WorkLED_on; } if(led_count>10)//10=1000ms { WorkLED_off; led_count=0; } //2 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm ad collection //2 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm ad collection if(main_count>5)//1=100ms { main_count=0; PPM_process(Gas_adc_value); if((gas_type==2)&&(O2_cail_switch==0)&&(o2_cail_count>(O2_cail_value_time*10))) { o2_cail_count=0; if((PPM<DEC_2_alarm)&&(PPM>DEC_1_alarm)) { if(PPM!=ppm_b) { temp_up=Gas_adc_value-set_ZERO; temp_up=temp_up*DEC_meas; temp_up=temp_up/209; temp_up=temp_up+set_ZERO; set_FULL=(u16)temp_up; I2C_writteword_24c_x(0x06,set_FULL); range = set_FULL-set_ZERO; } } } } //3 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm temperature instrucation //3 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm temperature instrucation //3 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm temperature instrucation if(temperature_count>100)//100*100ms=10s { if(temperature_error_flag==0)Read_TCN75(); temperature_count=0; Modbus_add_reg[10]=send_temp; dog_count=0; } //4 mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm oled UART4 service if(uart4_rx_ok_flag==1) { if(uart4_temp_buf[2]==0x03) //read reg { reg_add=uart4_temp_buf[3]; reg_count=uart4_temp_buf[5]; if(reg_count<120) { uart4_rx_count=0; Modbus_tx_buf[0]=sensor_add; Modbus_tx_buf[1]=0xbb; Modbus_tx_buf[2]=3; Modbus_tx_buf[3]=reg_count*2; for(i=0;i<reg_count;i++) { Modbus_tx_buf[4+i*2]=Modbus_add_reg[reg_add+i]>>8; Modbus_tx_buf[5+i*2]=Modbus_add_reg[reg_add+i]&0xff; } CRC_temp=CRC16_creat_TX(Modbus_tx_buf,4+i*2); Modbus_tx_buf[4+i*2]=CRC_temp>>8; Modbus_tx_buf[5+i*2]=CRC_temp&0xff; HAL_UART_Transmit(&huart4, Modbus_tx_buf,6+i*2,60000); } } else if(uart4_temp_buf[2]==0xa9)//init all { init_value(4); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WRITE_memory_init_value(); range = set_FULL-set_ZERO; Send_error_status(1);//SNG01 RS485_updata(); } else if(uart4_temp_buf[2]==0xa8)//init CURRENT GAS { init_value(gas_type); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WRITE_memory_init_value(); range = set_FULL-set_ZERO; Send_error_status(11);//SNG11 RS485_updata(); } else if(uart4_temp_buf[2]==0xBD)//Read 24C04 { for(i=0;i<200;i++) { Modbus_tx_buf[i+2]=I2C_read_BYTE_24c_x(i); } Modbus_tx_buf[0]=0xEE; Modbus_tx_buf[1]=0xEE; HAL_UART_Transmit(&huart4, Modbus_tx_buf,202,60000); } else if(uart4_temp_buf[2]==0xa0)//Cail zero { if(uart4_temp_buf[3]==0xa0) { set_ZERO=Gas_adc_value; I2C_writteword_24c_x(0x04,set_ZERO); for(a=0;a<10;a++)ppm_buf[a]=0; RS485_reg_updata_and_return_ok(0x04); range = set_FULL-set_ZERO; } } else if(uart4_temp_buf[2]==0xa1)//Cail full { if(uart4_temp_buf[3]==0xa1) { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; temp_u32=R_TEMP; if(gas_type==4) { temp_u32=temp_u32*100/Temperature_List[ofter_temp]; } temp_up=Gas_adc_value-set_ZERO; temp_up=temp_up*DEC_meas; temp_up=temp_up/temp_u32; temp_up=temp_up+set_ZERO; set_FULL=temp_up; for(a=0;a<10;a++)ppm_buf[a]=R_TEMP; I2C_writteword_24c_x(0x06,set_FULL); RS485_reg_updata_and_return_ok(0x06); range = set_FULL-set_ZERO; } } else if(uart4_temp_buf[2]==6) //write { reg_add=uart4_temp_buf[3]; switch(reg_add) { case 2://--------------- set alarm 1 value { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; DEC_1_alarm=R_TEMP; I2C_writteword_24c_x(0x08,DEC_1_alarm); RS485_reg_updata_and_return_ok(0x08); } break; case 3://--------------- set alarm 2 value { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; DEC_2_alarm=R_TEMP; I2C_writteword_24c_x(0x0a,DEC_2_alarm); RS485_reg_updata_and_return_ok(0x0A); } break; case 4://--------------- set alarm 3 value { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; DEC_3_alarm=R_TEMP; I2C_writteword_24c_x(0x0c,DEC_3_alarm); RS485_reg_updata_and_return_ok(0x0C); } break; case 5://--------------- set meas { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; temp_up=(range*100)/DEC_meas; temp_up*=R_TEMP; temp_up/=100; temp_up+=set_ZERO; set_FULL=temp_up; Modbus_tx_buf[13]=set_FULL; I2C_writteword_24c_x(0x06,set_FULL); range=set_FULL-set_ZERO; DEC_meas=R_TEMP; I2C_writteword_24c_x(0x02,DEC_meas); RS485_reg_updata_and_return_ok(0x02); } break; case 7://--------------- set gas_point { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; gas_point=R_TEMP; I2C_writteword_24c_x(0x14,gas_point); RS485_reg_updata_and_return_ok(0x14); } break; case 8://--------------- set gas_type { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; gas_type=R_TEMP; I2C_writteword_24c_x(0x18,gas_type); RS485_reg_updata_and_return_ok(0x18); init_value(gas_type); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WorkLED_on; Delay_Ms(10); WorkLED_off; Delay_Ms(100); WRITE_memory_init_value(); range = set_FULL-set_ZERO; RS485_updata(); } break; case 9://--------------- set gas_unit { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; gas_unit=R_TEMP; I2C_writteword_24c_x(0x16,gas_unit); RS485_reg_updata_and_return_ok(0x16); } break; case 12://-------------- adjust zero { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; set_ZERO=R_TEMP; Modbus_tx_buf[reg_add]=R_TEMP; I2C_writteword_24c_x(0x04,set_ZERO); RS485_reg_updata_and_return_ok(0x04); range = set_FULL-set_ZERO; } break; case 13://-------------- adjust full { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; set_FULL=R_TEMP; Modbus_tx_buf[reg_add]=R_TEMP; I2C_writteword_24c_x(0x06,set_FULL); RS485_reg_updata_and_return_ok(0x06); range = set_FULL-set_ZERO; } break; case 24://-------------- gas_disp_zero_value { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; gas_disp_zero_value=R_TEMP; I2C_writteword_24c_x(0x1A,gas_disp_zero_value); RS485_reg_updata_and_return_ok(0x1A); } break; case 27://-------------- O2_cail_switch { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; O2_cail_switch=R_TEMP; I2C_writteword_24c_x(0x20,O2_cail_switch); RS485_reg_updata_and_return_ok(0x20); } break; case 33://-------------- set baud { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; sensor_baud=R_TEMP; I2C_writteword_24c_x(0x10,sensor_baud); RS485_reg_updata_and_return_ok(0x10); } break; case 34://-------------- set asensor_add { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; sensor_add=R_TEMP; I2C_writteword_24c_x(0x12,sensor_add); RS485_reg_updata_and_return_ok(0x12); } break; case 35://-------------- set o2 cail low value { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; o2_cail_low_value=R_TEMP; I2C_writteword_24c_x(0x22,o2_cail_low_value); RS485_reg_updata_and_return_ok(0x22); } break; case 36://-------------- set o2 cail high value { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; o2_cail_high_value=R_TEMP; I2C_writteword_24c_x(0x24,o2_cail_high_value); RS485_reg_updata_and_return_ok(0x24); } break; case 37://-------------- set o2_disp_low_value { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; o2_disp_low_value=R_TEMP; I2C_writteword_24c_x(0x26,o2_disp_low_value); RS485_reg_updata_and_return_ok(0x26); } break; case 38://-------------- set o2_disp_high_value { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; o2_disp_high_value=R_TEMP; I2C_writteword_24c_x(0x28,o2_disp_high_value); RS485_reg_updata_and_return_ok(0x28); } break; case 39://-------------- set O2_cail_value_time { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; O2_cail_value_time=R_TEMP; I2C_writteword_24c_x(0x2A,O2_cail_value_time); RS485_reg_updata_and_return_ok(0x2A); } break; case 40://-------------- set wait_init_time { R_TEMP=uart4_temp_buf[4]; R_TEMP<<=8; R_TEMP+=uart4_temp_buf[5]; Modbus_tx_buf[reg_add]=R_TEMP; wait_init_time=R_TEMP; I2C_writteword_24c_x(0x2c,wait_init_time); RS485_reg_updata_and_return_ok(0x2c); } break; default: if((uart4_temp_buf[3]>=50)&&(uart4_temp_buf[3]<=200)) { I2C_writtebyte_24c_x(uart4_temp_buf[3]+30,uart4_temp_buf[5]); Modbus_add_reg[uart4_temp_buf[3]]=uart4_temp_buf[5]; uart4_rx_count=0; Modbus_tx_buf[0]=0XEE; Modbus_tx_buf[1]=0xEE; Modbus_tx_buf[2]=2; Modbus_tx_buf[3]=uart4_temp_buf[4]; Modbus_tx_buf[4]=uart4_temp_buf[5]; CRC_temp=CRC16_creat_TX(Modbus_tx_buf,5); Modbus_tx_buf[5]=CRC_temp>>8; Modbus_tx_buf[6]=CRC_temp&0xff; HAL_UART_Transmit(&huart4, Modbus_tx_buf,7,60000); } break; } //mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm //mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm } uart4_rx_ok_flag=0; } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1; RCC_OscInitStruct.PLL.PLLN = 8; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } /** * @brief ADC1 Initialization Function * @param None * @retval None */ static void MX_ADC1_Init(void) { /* USER CODE BEGIN ADC1_Init 0 */ /* USER CODE END ADC1_Init 0 */ ADC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN ADC1_Init 1 */ /* USER CODE END ADC1_Init 1 */ /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.LowPowerAutoPowerOff = DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.NbrOfConversion = 1; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DMAContinuousRequests = ENABLE; hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_3CYCLES_5; hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_3CYCLES_5; hadc1.Init.OversamplingMode = DISABLE; hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_11; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ } /** * @brief TIM3 Initialization Function * @param None * @retval None */ static void MX_TIM3_Init(void) { /* USER CODE BEGIN TIM3_Init 0 */ /* USER CODE END TIM3_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; /* USER CODE BEGIN TIM3_Init 1 */ /* USER CODE END TIM3_Init 1 */ htim3.Instance = TIM3; htim3.Init.Prescaler = 6399; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 999; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim3) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN TIM3_Init 2 */ /* USER CODE END TIM3_Init 2 */ } /** * @brief USART4 Initialization Function * @param None * @retval None */ static void MX_USART4_UART_Init(void) { /* USER CODE BEGIN USART4_Init 0 */ /* USER CODE END USART4_Init 0 */ /* USER CODE BEGIN USART4_Init 1 */ /* USER CODE END USART4_Init 1 */ huart4.Instance = USART4; huart4.Init.BaudRate = 19200; huart4.Init.WordLength = UART_WORDLENGTH_8B; huart4.Init.StopBits = UART_STOPBITS_1; huart4.Init.Parity = UART_PARITY_NONE; huart4.Init.Mode = UART_MODE_TX_RX; huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart4.Init.OverSampling = UART_OVERSAMPLING_16; huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1; huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart4) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART4_Init 2 */ HAL_UART_Receive_IT(&huart4,Rx4,1); /* USER CODE END USART4_Init 2 */ } /** * Enable DMA controller clock */ static void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Channel1_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn); } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* USER CODE BEGIN MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */ /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ //HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET); /*Configure GPIO pins : PB11 PB12 */ GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pin : PC6 */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // /*Configure GPIO pin : PC6 */ // GPIO_InitStruct.Pin = GPIO_PIN_6; // GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // GPIO_InitStruct.Pull = GPIO_NOPULL; // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); // GPIO_InitStruct.Pin = GPIO_PIN_12; // GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // GPIO_InitStruct.Pull = GPIO_NOPULL; // GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PC7 */ GPIO_InitStruct.Pin = GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pin : PA15 */ GPIO_InitStruct.Pin = GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PD0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /*Configure GPIO pin : PB9 */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ } /* USER CODE BEGIN 4 */ //aa bb 03 70 reg count crc2(8bytes) u8 u; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART4) { uart4_rx_buf[uart4_rx_count]=Rx4[0]; uart4_rx_count++; if(uart_work_flag==1) { switch(uart4_rx_count) { case 1: if(uart4_rx_buf[0]!=sensor_add)uart4_rx_count=0; break; case 2: if(uart4_rx_buf[1]!=0xAA) { if(uart4_rx_buf[1]==sensor_add)uart4_rx_count=1; else uart4_rx_count=0; } break; case 8: for(u=0;u<8;u++)uart4_temp_buf[u]=uart4_rx_buf[u]; if(CRC16_creat_RX(uart4_temp_buf,8)) { uart4_rx_ok_flag=1; } uart4_rx_count=0; break; default: break; } } else { uart4_rx_count=0; } HAL_UART_Receive_IT(&huart4,Rx4,1); } } u16 AD1_buf[30]; u32 AD_add; u8 AD1_count; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//100ms { if(htim == &htim3) { add_adc=0; for(Pi=10;Pi<266;Pi+=4)add_adc+=adc_buf[Pi]; add_adc>>=6; AD1_buf[AD1_count++]=(u16)add_adc; if(AD1_count>=30)AD1_count=0; AD_add=0; for(Pi=0;Pi<30;Pi++)AD_add+=AD1_buf[Pi]; AD_add=AD_add/30; Gas_adc_value=(u16)AD_add; if(gas_type==7)Gas_adc_value=4096-Gas_adc_value; if(gas_type==8)Gas_adc_value=4096-Gas_adc_value; Modbus_add_reg[11] = Gas_adc_value; //-------------------------------------------- main_count++; temperature_count++; led_count++; dog_count++; if(o2_cail_count_flag==1)o2_cail_count++; if(dog_count>6000)//after 600S,then restart { NVIC_SystemReset(); } } } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ 有使用温度补偿的地方吗
最新发布
10-28
void my_delay(int n) { int i = 0; while(n--) for(i=0; i<8050; i++); } #define proport 10000 #define L1 ((proport/131)-1)//低调 do 的周期 #define L2 ((proport/147)-1)//低调 re 的周期 #define L3 ((proport/165)-1)//低调 mi 的周期 #define L4 ((proport/176)-1)//低调 fa 的周期 #define L5 ((proport/196)-1)//低调 sol 的周期 #define L6 ((proport/220)-1)//低调 la的周期 #define L7 ((proport/247)-1)//低调 si 的周期 #define M1 ((proport/262)-1)//低调 do 的周期 #define M2 ((proport/296)-1)//低调 re 的周期 #define M3 ((proport/330)-1)//低调 mi 的周期 #define M4 ((proport/349)-1)//低调 fa 的周期 #define M5 ((proport/392)-1)//低调 sol 的周期 #define M6 ((proport/440)-1)//低调 la 的周期 #define M7 ((proport/494)-1)//低调 si 的周期 #define H1 ((proport/523)-1)//低调 do 的周期 #define H2 ((proport/587)-1)//低调 re 的周期 #define H3 ((proport/659)-1)//低调 mi 的周期 #define H4 ((proport/699)-1)//低调 fa 的周期 #define H5 ((proport/784)-1)//低调 sol 的周期 #define H6 ((proport/880)-1)//低调 la 的周期 #define H7 ((proport/988)-1)//低调 si 的周期void Pwm_Gpio_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA的时钟 //GPIO配置 PA6 TIM3_CH1 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //引脚初始化 } void Tim2_Pwm_Set(int Period, int Pulse) { TIM_TimeBaseInitTypeDef TIM_BaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM3的时钟 //TIM2的基本配置 TIM_BaseInitStructure.TIM_Prescaler = 7200-1;//预分频 TIM_BaseInitStructure.TIM_Period = Period;//计数周期 TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数 TIM_BaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割 输入滤波 TIM_TimeBaseInit(TIM2, &TIM_BaseInitStructure);//初始化TIM2 //配置TIM2的通道1输出PWM脉冲 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//TIM 脉冲宽度调制模式 1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//定时器输出使能 TIM_OCInitStructure.TIM_Pulse = Pulse;//设置装入捕获比较寄存器的脉冲值 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM 输出比较极性:高 即周期内低于TIM_Pulse这个阈值的时间,都是高电平,其他时间都是低; TIM_OC1Init(TIM2,&TIM_OCInitStructure);//初始化TIM2的Channel1 TIM_Cmd(TIM2,ENABLE);//使能TIM2 } void Set_Rate(int rate) { if((rate >= 0) && (rate < 400)) TIM_SetCompare1(TIM2, rate); else return;int music1[]= { M5,50,M5,25,M5,25, M6,100,M5,100,H1,100, M7,100,M7,100,M5,50,M5,25,M5,25, M6,100,M5,100,H2,100, H1,100,H1,100,M5,50,M5,25,M5,25, H5,100,H3,100,H1,100, M7,100,M6,100,H4,50,H4,25,H4,25, H3,100,H1,100,H2,100,H1,100,H1,100 };music1是生日快乐歌,我需要你写出警报时的警报音
03-22
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值