MACHINE_START and MACHINE_END Macro define

***************************************************************************************************************************
作者:EasyWave                                                                                 时间:2012.02.11

类别:linux驱动开发                                                                           声明:转载,请保留链接

***************************************************************************************************************************

在linux-2.6.38中,/arch/arm/mach-w90x900/mach-nuc950evb.c文件的最后部分,有如下宏定义:

MACHINE_START(W90P950EVB, "W90P950EVB")
 .phys_io = W90X900_PA_UART,
 .io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc, 
 .boot_params =  0x100,
 .map_io  = nuc950evb_map_io,
 .init_irq = nuc900_init_irq,
 .init_machine = nuc950evb_init,
 .timer  = &nuc900_timer,
MACHINE_END

 

而MACHINE_START和MACHINE_END宏定义在arch/arm/include/asm/mach/arch.h,如下:

struct machine_desc {
 /*
  * Note! The first four elements are used
  * by assembler code in head.S, head-common.S
  */
 unsigned int  nr;  /* architecture number */
 unsigned int  phys_io; /* start of physical io */
 unsigned int  io_pg_offst; /* byte offset for io
       * page tabe entry */

 const char  *name;  /* architecture name */
 unsigned long  boot_params; /* tagged list  */

 unsigned int  video_start; /* start of video RAM */
 unsigned int  video_end; /* end of video RAM */

 unsigned int  reserve_lp0 :1; /* never has lp0 */
 unsigned int  reserve_lp1 :1; /* never has lp1 */
 unsigned int  reserve_lp2 :1; /* never has lp2 */
 unsigned int  soft_reboot :1; /* soft reboot  */
 void   (*fixup)(struct machine_desc *,     struct tag *, char **,   struct meminfo *);
 void   (*map_io)(void);/* IO mapping function */
 void   (*init_irq)(void);
 struct sys_timer *timer;  /* system tick timer */
 void   (*init_machine)(void);
};

/*
 * Set of macros to define architecture features.  This is built into
 * a table by the linker.
 */
#define MACHINE_START(_type,_name)   \
static const struct machine_desc __mach_desc_##_type \
 __used       \
 __attribute__((__section__(".arch.info.init"))) = { \
 .nr  = MACH_TYPE_##_type,  \
 .name  = _name,

#define MACHINE_END    \
};

#endif

 

将前面定义的MACHINE_START和MACHINE_END展开后得到:
static  const struct machine_desc __mach_desc_W90P950EVB __used __attribute__((__section__(".arch.info.init"))) = {
.nr = MACH_TYPE_W90P950EVB, /* architecture number */
.name = "W90P950EVB"", /* architecture name */
.phys_io = W90X900_PA_UART, /* start of physical io */
.io_pg_offst = (((u32)W90X900_VA_UART) >> 18) & 0xfffc,
.boot_params = 0x100, /* tagged list */
.map_io = nuc950evb_map_io, /* IO mapping function */
.init_irq = nuc900_init_irq,
.init_machine = nuc950evb_init,
.timer = &nuc900_timer,
}

MACH_TYPE_W90P950EVB定义在arch/arm/include/asm/mach-types.h内,值为1860 十六进制为:0x744.
#define MACH_TYPE_W90P950EVB             1860

这个值是机器的类型值,编译时由arch/arm/tool/mach- types里面定义的数据生成的。
/* arch/arm/tool/mach-types */
w90x900   MACH_W90X900  W90X900   1860

而在arch/arm/kernel/head-common.S文件中的__lookup_machine_type函数中有如下的定义:

/*
 *  linux/arch/arm/kernel/head-common.S
 *
 *  Copyright (C) 1994-2002 Russell King
 *  Copyright (c) 2003 ARM Limited
 *  All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#define ATAG_CORE 0x54410001
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)

 .align 2
 .type __switch_data, %object
__switch_data:
...................中间省略

 .long processor_id                   @ r4
 .long __machine_arch_type    @ r5
 .long __atags_pointer              @ r6
 .long cr_alignment                   @ r7
 .long init_thread_union + THREAD_START_SP  @ sp

 ...................中间省略

/*
 * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for
 * more information about the __proc_info and __arch_info structures.
 */
 .align 2
3: .long __proc_info_begin
 .long __proc_info_end
4: .long .
 .long __arch_info_begin
 .long __arch_info_end

/*
 * Lookup machine architecture in the linker-build list of architectures.
 * Note that we can't use the absolute addresses for the __arch_info
 * lists since we aren't running with the MMU on (and therefore, we are
 * not in the correct address space).  We have to calculate the offset.
 *
 *  r1 = machine architecture number
 * Returns:
 *  r3, r4, r6 corrupted
 *  r5 = mach_info pointer in physical address space
 */
__lookup_machine_type:
#ifdef CONFIG_ARCH_W90X900     //这个就是前面的1860,十六进制为:0x744
       mov      r1, #0x700
       add      r1, r1, #0x40
       add      r1, r1, #0x04
#endif
 adr r3, 4b
 ldmia r3, {r4, r5, r6}
 sub r3, r3, r4   @ get offset between virt&phys
 add r5, r5, r3   @ convert virt addresses to
 add r6, r6, r3   @ physical address space
1: ldr r3, [r5, #MACHINFO_TYPE] @ get machine type
 teq r3, r1    @ matches loader number?
 beq 2f    @ found
 add r5, r5, #SIZEOF_MACHINE_DESC @ next machine_desc
 cmp r5, r6
 blo 1b
 mov r5, #0    @ unknown machine
2: mov pc, lr
ENDPROC(__lookup_machine_type)

函数说明:

adr r3,4b : 取地址指令,这里的4b 是向后symbol名称是4的位置,即4: .long .的位置,将该地址存入r3,r3中存放的是4b处物理地址.
        r5存的是__arch_info_begin 的地址
        r6存的是__arch_info_end 的地址


arm linux 从入口到start_kernel 代码分析

__arch_info_begin 和 __arch_info_end是在 arch/arm/kernel/vmlinux.lds.S中:

          __arch_info_begin = .;
          *(.arch.info.init)
          __arch_info_end = .;    

        这里是声明了两个变量:__arch_info_begin 和 __arch_info_end,其中等号后面的"."是location counter(详细内容请参考ld.info),这三行的意思是: __arch_info_begin 的位置上,放置所有文件中的 ".arch.info.init" 段的内容,然后紧接着是 __arch_info_end 的位置.

teq r3, r1    @ matches loader number?
如果R1中存储的值和mach-types.h不一致的话,会出现下面的错误:

Machine configuration botched (nr xxxx), unable to continue.不同的版本会出现的警报不一致。

在arch/arm/kernel/setup.c中:

void __init setup_arch(char **cmdline_p)
{
 struct tag *tags = (struct tag *)&init_tags;
 struct machine_desc *mdesc;
 char *from = default_command_line;

 unwind_init();

 setup_processor();
 mdesc = setup_machine(machine_arch_type);
 machine_name = mdesc->name;

 if (mdesc->soft_reboot)
  reboot_setup("s");

 if (__atags_pointer)
  tags = phys_to_virt(__atags_pointer);
 else if (mdesc->boot_params)
  tags = phys_to_virt(mdesc->boot_params);

 /*
  * If we have the old style parameters, convert them to
  * a tag list.
  */
 if (tags->hdr.tag != ATAG_CORE)
  convert_to_tag_list(tags);
 if (tags->hdr.tag != ATAG_CORE)
  tags = (struct tag *)&init_tags;

 if (mdesc->fixup)
  mdesc->fixup(mdesc, tags, &from, &meminfo);

 if (tags->hdr.tag == ATAG_CORE) {
  if (meminfo.nr_banks != 0)
   squash_mem_tags(tags);
  save_atags(tags);
  parse_tags(tags);
 }

 init_mm.start_code = (unsigned long) _text;
 init_mm.end_code   = (unsigned long) _etext;
 init_mm.end_data   = (unsigned long) _edata;
 init_mm.brk    = (unsigned long) _end;

 /* parse_early_param needs a boot_command_line */
 strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);

 /* populate cmd_line too for later use, preserving boot_command_line */
 strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
 *cmdline_p = cmd_line;

 parse_early_param();

 paging_init(mdesc);
 request_standard_resources(&meminfo, mdesc);

#ifdef CONFIG_SMP
 smp_init_cpus();
#endif

 cpu_init();
 tcm_init();

 /*
  * Set up various architecture-specific pointers
  */
 init_arch_irq = mdesc->init_irq;
 system_timer = mdesc->timer;
 init_machine = mdesc->init_machine;

#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
 conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
 conswitchp = &dummy_con;
#endif
#endif
 early_trap_init();
}

而setup_machine(unsigned int nr)函数也是在arch/arm/kernel/setup.c中定义:

static struct machine_desc * __init setup_machine(unsigned int nr)
{
 struct machine_desc *list;

 /*
  * locate machine in the list of supported machines.
  */
 list = lookup_machine_type(nr); //看到了吧,这个才是重点
 if (!list) {
  printk("Machine configuration botched (nr %d), unable "
         "to continue.\n", nr);
  while (1);
 }

 printk("Machine: %s\n", list->name);

 return list;
}

因此就会出现:Machine configuration botched (nr xxxx), unable to continue.的警告信息。

 

各个成员函数在不同时期被调用:
1. .init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall() 段里面,会自动按顺序被调用。
2. init_irq在start_kernel() --> init_IRQ() --> init_arch_irq() 被调用
3. map_io 在 setup_arch() --> paging_init() --> devicemaps_init()被调用
其他主要都在 setup_arch() 中用到。

/* * linux/arch/arm/kernel/head.S * * Copyright (C) 1994-2002 Russell King * Copyright (c) 2003 ARM Limited * All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Kernel startup code for all 32-bit CPUs */ #include <linux/linkage.h> #include <linux/init.h> #include <asm/assembler.h> #include <asm/cp15.h> #include <asm/domain.h> #include <asm/ptrace.h> #include <asm/asm-offsets.h> #include <asm/memory.h> #include <asm/thread_info.h> #include <asm/pgtable.h> #if defined(CONFIG_DEBUG_LL) && !defined(CONFIG_DEBUG_SEMIHOSTING) #include CONFIG_DEBUG_LL_INCLUDE #endif /* * swapper_pg_dir is the virtual address of the initial page table. * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must * make sure that KERNEL_RAM_VADDR is correctly set. Currently, we expect * the least significant 16 bits to be 0x8000, but we could probably * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000. */ #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) #if (KERNEL_RAM_VADDR & 0xffff) != 0x8000 #error KERNEL_RAM_VADDR must start at 0xXXXX8000 #endif #ifdef CONFIG_ARM_LPAE /* LPAE requires an additional page for the PGD */ #define PG_DIR_SIZE 0x5000 #define PMD_ORDER 3 #else #define PG_DIR_SIZE 0x4000 #define PMD_ORDER 2 #endif .globl swapper_pg_dir .equ swapper_pg_dir, KERNEL_RAM_VADDR - PG_DIR_SIZE .macro pgtbl, rd, phys add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE .endm /* * Kernel startup entry point. * --------------------------- * * This is normally called from the decompressor code. The requirements * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, * r1 = machine nr, r2 = atags or dtb pointer. * * This code is mostly position independent, so if you link the kernel at * 0xc0008000, you call this at __pa(0xc0008000). * * See linux/arch/arm/tools/mach-types for the complete list of machine * numbers for r1. * * We're trying to keep crap to a minimum; DO NOT add any machine specific * crap here - that's what the boot loader (or in extreme, well justified * circumstances, zImage) is for. */ .arm __HEAD ENTRY(stext) THUMB( adr r9, BSYM(1f) ) @ Kernel is always entered in ARM. THUMB( bx r9 ) @ If this is a Thumb-2 kernel, THUMB( .thumb ) @ switch to Thumb now. THUMB(1: ) #ifdef CONFIG_ARM_VIRT_EXT bl __hyp_stub_install #endif @ ensure svc mode and all interrupts masked safe_svcmode_maskall r9 mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type @ r5=procinfo r9=cpuid movs r10, r5 @ invalid processor (r5=0)? THUMB( it eq ) @ force fixup-able long branch encoding beq __error_p @ yes, error 'p' #ifdef CONFIG_ARM_LPAE mrc p15, 0, r3, c0, c1, 4 @ read ID_MMFR0 and r3, r3, #0xf @ extract VMSA support cmp r3, #5 @ long-descriptor translation table format? THUMB( it lo ) @ force fixup-able long branch encoding blo __error_p @ only classic page table format #endif #ifndef CONFIG_XIP_KERNEL adr r3, 2f ldmia r3, {r4, r8} sub r4, r3, r4 @ (PHYS_OFFSET - PAGE_OFFSET) add r8, r8, r4 @ PHYS_OFFSET #else ldr r8, =PHYS_OFFSET @ always constant in this case #endif /* * r1 = machine no, r2 = atags or dtb, * r8 = phys_offset, r9 = cpuid, r10 = procinfo */ bl __vet_atags #ifdef CONFIG_SMP_ON_UP bl __fixup_smp #endif #ifdef CONFIG_ARM_PATCH_PHYS_VIRT bl __fixup_pv_table #endif bl __create_page_tables /* * The following calls CPU specific code in a position independent * manner. See arch/arm/mm/proc-*.S for details. r10 = base of * xxx_proc_info structure selected by __lookup_processor_type * above. On return, the CPU will be ready for the MMU to be * turned on, and r0 will hold the CPU control register value. */ ldr r13, =__mmap_switched @ address to jump to after @ mmu has been enabled adr lr, BSYM(1f) @ return (PIC) address mov r8, r4 @ set TTBR1 to swapper_pg_dir ARM( add pc, r10, #PROCINFO_INITFUNC ) THUMB( add r12, r10, #PROCINFO_INITFUNC ) THUMB( mov pc, r12 ) 1: b __enable_mmu ENDPROC(stext) .ltorg #ifndef CONFIG_XIP_KERNEL 2: .long . .long PAGE_OFFSET #endif /* * Setup the initial page tables. We only setup the barest * amount which are required to get the kernel running, which * generally means mapping in the kernel code. * * r8 = phys_offset, r9 = cpuid, r10 = procinfo * * Returns: * r0, r3, r5-r7 corrupted * r4 = physical page table address */ __create_page_tables: pgtbl r4, r8 @ page table address /* * Clear the swapper page table */ mov r0, r4 mov r3, #0 add r6, r0, #PG_DIR_SIZE 1: str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 str r3, [r0], #4 teq r0, r6 bne 1b #ifdef CONFIG_ARM_LPAE /* * Build the PGD table (first level) to point to the PMD table. A PGD * entry is 64-bit wide. */ mov r0, r4 add r3, r4, #0x1000 @ first PMD table address orr r3, r3, #3 @ PGD block type mov r6, #4 @ PTRS_PER_PGD mov r7, #1 << (55 - 32) @ L_PGD_SWAPPER 1: #ifdef CONFIG_CPU_ENDIAN_BE8 str r7, [r0], #4 @ set top PGD entry bits str r3, [r0], #4 @ set bottom PGD entry bits #else str r3, [r0], #4 @ set bottom PGD entry bits str r7, [r0], #4 @ set top PGD entry bits #endif add r3, r3, #0x1000 @ next PMD table subs r6, r6, #1 bne 1b add r4, r4, #0x1000 @ point to the PMD tables #ifdef CONFIG_CPU_ENDIAN_BE8 add r4, r4, #4 @ we only write the bottom word #endif #endif ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags /* * Create identity mapping to cater for __enable_mmu. * This identity mapping will be removed by paging_init(). */ adr r0, __turn_mmu_on_loc ldmia r0, {r3, r5, r6} sub r0, r0, r3 @ virt->phys offset add r5, r5, r0 @ phys __turn_mmu_on add r6, r6, r0 @ phys __turn_mmu_on_end mov r5, r5, lsr #SECTION_SHIFT mov r6, r6, lsr #SECTION_SHIFT 1: orr r3, r7, r5, lsl #SECTION_SHIFT @ flags + kernel base str r3, [r4, r5, lsl #PMD_ORDER] @ identity mapping cmp r5, r6 addlo r5, r5, #1 @ next section blo 1b /* * Map our RAM from the start to the end of the kernel .bss section. */ add r0, r4, #PAGE_OFFSET >> (SECTION_SHIFT - PMD_ORDER) ldr r6, =(_end - 1) orr r3, r8, r7 add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 1: str r3, [r0], #1 << PMD_ORDER add r3, r3, #1 << SECTION_SHIFT cmp r0, r6 bls 1b #ifdef CONFIG_XIP_KERNEL /* * Map the kernel image separately as it is not located in RAM. */ #define XIP_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) mov r3, pc mov r3, r3, lsr #SECTION_SHIFT orr r3, r7, r3, lsl #SECTION_SHIFT add r0, r4, #(XIP_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) str r3, [r0, #((XIP_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! ldr r6, =(_edata_loc - 1) add r0, r0, #1 << PMD_ORDER add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 1: cmp r0, r6 add r3, r3, #1 << SECTION_SHIFT strls r3, [r0], #1 << PMD_ORDER bls 1b #endif /* * Then map boot params address in r2 if specified. * We map 2 sections in case the ATAGs/DTB crosses a section boundary. */ mov r0, r2, lsr #SECTION_SHIFT movs r0, r0, lsl #SECTION_SHIFT subne r3, r0, r8 addne r3, r3, #PAGE_OFFSET addne r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) orrne r6, r7, r0 strne r6, [r3], #1 << PMD_ORDER addne r6, r6, #1 << SECTION_SHIFT strne r6, [r3] #if defined(CONFIG_ARM_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8) sub r4, r4, #4 @ Fixup page table pointer @ for 64-bit descriptors #endif #ifdef CONFIG_DEBUG_LL #if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING) /* * Map in IO space for serial debugging. * This allows debug messages to be output * via a serial console before paging_init. */ addruart r7, r3, r0 mov r3, r3, lsr #SECTION_SHIFT mov r3, r3, lsl #PMD_ORDER add r0, r4, r3 mov r3, r7, lsr #SECTION_SHIFT ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags orr r3, r7, r3, lsl #SECTION_SHIFT #ifdef CONFIG_ARM_LPAE mov r7, #1 << (54 - 32) @ XN #ifdef CONFIG_CPU_ENDIAN_BE8 str r7, [r0], #4 str r3, [r0], #4 #else str r3, [r0], #4 str r7, [r0], #4 #endif #else orr r3, r3, #PMD_SECT_XN str r3, [r0], #4 #endif #else /* CONFIG_DEBUG_ICEDCC || CONFIG_DEBUG_SEMIHOSTING */ /* we don't need any serial debugging mappings */ ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags #endif #if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS) /* * If we're using the NetWinder or CATS, we also need to map * in the 16550-type serial port for the debug messages */ add r0, r4, #0xff000000 >> (SECTION_SHIFT - PMD_ORDER) orr r3, r7, #0x7c000000 str r3, [r0] #endif #ifdef CONFIG_ARCH_RPC /* * Map in screen at 0x02000000 & SCREEN2_BASE * Similar reasons here - for debug. This is * only for Acorn RiscPC architectures. */ add r0, r4, #0x02000000 >> (SECTION_SHIFT - PMD_ORDER) orr r3, r7, #0x02000000 str r3, [r0] add r0, r4, #0xd8000000 >> (SECTION_SHIFT - PMD_ORDER) str r3, [r0] #endif #endif #ifdef CONFIG_ARM_LPAE sub r4, r4, #0x1000 @ point to the PGD table #endif mov pc, lr ENDPROC(__create_page_tables) .ltorg .align __turn_mmu_on_loc: .long . .long __turn_mmu_on .long __turn_mmu_on_end #if defined(CONFIG_SMP) __CPUINIT ENTRY(secondary_startup) /* * Common entry point for secondary CPUs. * * Ensure that we're in SVC mode, and IRQs are disabled. Lookup * the processor type - there is no need to check the machine type * as it has already been validated by the primary processor. */ #ifdef CONFIG_ARM_VIRT_EXT bl __hyp_stub_install_secondary #endif safe_svcmode_maskall r9 mrc p15, 0, r9, c0, c0 @ get processor id bl __lookup_processor_type movs r10, r5 @ invalid processor? moveq r0, #'p' @ yes, error 'p' THUMB( it eq ) @ force fixup-able long branch encoding beq __error_p /* * Use the page tables supplied from __cpu_up. */ adr r4, __secondary_data ldmia r4, {r5, r7, r12} @ address to jump to after sub lr, r4, r5 @ mmu has been enabled ldr r4, [r7, lr] @ get secondary_data.pgdir add r7, r7, #4 ldr r8, [r7, lr] @ get secondary_data.swapper_pg_dir adr lr, BSYM(__enable_mmu) @ return address mov r13, r12 @ __secondary_switched address ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor @ (return control reg) THUMB( add r12, r10, #PROCINFO_INITFUNC ) THUMB( mov pc, r12 ) ENDPROC(secondary_startup) /* * r6 = &secondary_data */ ENTRY(__secondary_switched) ldr sp, [r7, #4] @ get secondary_data.stack mov fp, #0 b secondary_start_kernel ENDPROC(__secondary_switched) .align .type __secondary_data, %object __secondary_data: .long . .long secondary_data .long __secondary_switched #endif /* defined(CONFIG_SMP) */ /* * Setup common bits before finally enabling the MMU. Essentially * this is just loading the page table pointer and domain access * registers. * * r0 = cp#15 control register * r1 = machine ID * r2 = atags or dtb pointer * r4 = page table pointer * r9 = processor ID * r13 = *virtual* address to jump to upon completion */ __enable_mmu: #if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6 orr r0, r0, #CR_A #else bic r0, r0, #CR_A #endif #ifdef CONFIG_CPU_DCACHE_DISABLE bic r0, r0, #CR_C #endif #ifdef CONFIG_CPU_BPREDICT_DISABLE bic r0, r0, #CR_Z #endif #ifdef CONFIG_CPU_ICACHE_DISABLE bic r0, r0, #CR_I #endif #ifdef CONFIG_ARM_LPAE mov r5, #0 mcrr p15, 0, r4, r5, c2 @ load TTBR0 #else mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \ domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \ domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \ domain_val(DOMAIN_IO, DOMAIN_CLIENT)) mcr p15, 0, r5, c3, c0, 0 @ load domain access register mcr p15, 0, r4, c2, c0, 0 @ load page table pointer #endif b __turn_mmu_on ENDPROC(__enable_mmu) /* * Enable the MMU. This completely changes the structure of the visible * memory space. You will not be able to trace execution through this. * If you have an enquiry about this, *please* check the linux-arm-kernel * mailing list archives BEFORE sending another post to the list. * * r0 = cp#15 control register * r1 = machine ID * r2 = atags or dtb pointer * r9 = processor ID * r13 = *virtual* address to jump to upon completion * * other registers depend on the function called upon completion */ .align 5 .pushsection .idmap.text, "ax" ENTRY(__turn_mmu_on) mov r0, r0 instr_sync mcr p15, 0, r0, c1, c0, 0 @ write control reg mrc p15, 0, r3, c0, c0, 0 @ read id reg instr_sync mov r3, r3 mov r3, r13 mov pc, r3 __turn_mmu_on_end: ENDPROC(__turn_mmu_on) .popsection #ifdef CONFIG_SMP_ON_UP __INIT __fixup_smp: and r3, r9, #0x000f0000 @ architecture version teq r3, #0x000f0000 @ CPU ID supported? bne __fixup_smp_on_up @ no, assume UP bic r3, r9, #0x00ff0000 bic r3, r3, #0x0000000f @ mask 0xff00fff0 mov r4, #0x41000000 orr r4, r4, #0x0000b000 orr r4, r4, #0x00000020 @ val 0x4100b020 teq r3, r4 @ ARM 11MPCore? moveq pc, lr @ yes, assume SMP mrc p15, 0, r0, c0, c0, 5 @ read MPIDR and r0, r0, #0xc0000000 @ multiprocessing extensions and teq r0, #0x80000000 @ not part of a uniprocessor system? moveq pc, lr @ yes, assume SMP __fixup_smp_on_up: adr r0, 1f ldmia r0, {r3 - r5} sub r3, r0, r3 add r4, r4, r3 add r5, r5, r3 b __do_fixup_smp_on_up ENDPROC(__fixup_smp) .align 1: .word . .word __smpalt_begin .word __smpalt_end .pushsection .data .globl smp_on_up smp_on_up: ALT_SMP(.long 1) ALT_UP(.long 0) .popsection #endif .text __do_fixup_smp_on_up: cmp r4, r5 movhs pc, lr ldmia r4!, {r0, r6} ARM( str r6, [r0, r3] ) THUMB( add r0, r0, r3 ) #ifdef __ARMEB__ THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. #endif THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. THUMB( strh r6, [r0] ) b __do_fixup_smp_on_up ENDPROC(__do_fixup_smp_on_up) ENTRY(fixup_smp) stmfd sp!, {r4 - r6, lr} mov r4, r0 add r5, r0, r1 mov r3, #0 bl __do_fixup_smp_on_up ldmfd sp!, {r4 - r6, pc} ENDPROC(fixup_smp) #ifdef CONFIG_ARM_PATCH_PHYS_VIRT /* __fixup_pv_table - patch the stub instructions with the delta between * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and * can be expressed by an immediate shifter operand. The stub instruction * has a form of '(add|sub) rd, rn, #imm'. */ __HEAD __fixup_pv_table: adr r0, 1f ldmia r0, {r3-r5, r7} sub r3, r0, r3 @ PHYS_OFFSET - PAGE_OFFSET add r4, r4, r3 @ adjust table start address add r5, r5, r3 @ adjust table end address add r7, r7, r3 @ adjust __pv_phys_offset address str r8, [r7] @ save computed PHYS_OFFSET to __pv_phys_offset mov r6, r3, lsr #24 @ constant for add/sub instructions teq r3, r6, lsl #24 @ must be 16MiB aligned THUMB( it ne @ cross section branch ) bne __error str r6, [r7, #4] @ save to __pv_offset b __fixup_a_pv_table ENDPROC(__fixup_pv_table) .align 1: .long . .long __pv_table_begin .long __pv_table_end 2: .long __pv_phys_offset .text __fixup_a_pv_table: #ifdef CONFIG_THUMB2_KERNEL lsls r6, #24 beq 2f clz r7, r6 lsr r6, #24 lsl r6, r7 bic r6, #0x0080 lsrs r7, #1 orrcs r6, #0x0080 orr r6, r6, r7, lsl #12 orr r6, #0x4000 b 2f 1: add r7, r3 ldrh ip, [r7, #2] and ip, 0x8f00 orr ip, r6 @ mask in offset bits 31-24 strh ip, [r7, #2] 2: cmp r4, r5 ldrcc r7, [r4], #4 @ use branch for delay slot bcc 1b bx lr #else b 2f 1: ldr ip, [r7, r3] bic ip, ip, #0x000000ff orr ip, ip, r6 @ mask in offset bits 31-24 str ip, [r7, r3] 2: cmp r4, r5 ldrcc r7, [r4], #4 @ use branch for delay slot bcc 1b mov pc, lr #endif ENDPROC(__fixup_a_pv_table) ENTRY(fixup_pv_table) stmfd sp!, {r4 - r7, lr} ldr r2, 2f @ get address of __pv_phys_offset mov r3, #0 @ no offset mov r4, r0 @ r0 = table start add r5, r0, r1 @ r1 = table size ldr r6, [r2, #4] @ get __pv_offset bl __fixup_a_pv_table ldmfd sp!, {r4 - r7, pc} ENDPROC(fixup_pv_table) .align 2: .long __pv_phys_offset .data .globl __pv_phys_offset .type __pv_phys_offset, %object __pv_phys_offset: .long 0 .size __pv_phys_offset, . - __pv_phys_offset __pv_offset: .long 0 #endif #include "head-common.S" 解释以上代码
09-24
#ifndef __DXS_H__ #define __DXS_H__ /****************************************************************************** Copyright (c) 2006-2015 Lantiq Deutschland GmbH Copyright (c) 2015 Lantiq Beteiligungs-GmbH & Co.KG Copyright 2018, Intel Corporation. For licensing information, see the file 'LICENSE' in the root folder of this software module. ******************************************************************************/ /** \file dxs.h This file contains the type definitions and function prototypes specific to the DXS library interface and is used by applications. */ /* ========================================================================== */ /* Includes */ /* ========================================================================== */ #include <stdint.h> /* ========================================================================== */ /* Macro definitions */ /* ========================================================================== */ #define DXS_API_VERSION_REG(a,b,c) (((a)<<16)|((b)<<8)|(c)) #define DXS_API_VERSION DXS_API_VERSION_REG(5,0,0) /** \defgroup DXS_API DXS API Device Driver Interface Reference This section describes functional interfaces, also called DXS API device driver interfaces. @{ */ /** \defgroup DXS_INITIALIZATION Initialization Device initialization API. */ /** \defgroup DXS_CONFIGURATION Configuration Device configuration API. */ /** \defgroup DXS_CONTROL Control Line mode control API. */ /** \defgroup DXS_DEBUG Debug Debug low level API. */ /** \defgroup DXS_TONE_GENERATION Tone Generation Tone generator control API. */ /** \defgroup DXS_CID_GENERATION Caller ID Generation Caller ID generator control API. */ /** \defgroup DXS_RING_CADENCE Ringing service Ring cadence configuration API. */ /** \defgroup DXS_FSK_GENERATION FSK Generation FSK generator control API. */ /** \defgroup DXS_TONE_DETECTION Tone Detection Universal Tone Detector control API. */ /** \defgroup DXS_DTMF_DETECTION DTMF Detection DTMF detector control API. */ /** \defgroup DXS_METERING TTX Metering Teletax Metering pulse generation control API. */ /** \defgroup DXS_CONTINUOUS_MEASUREMENTS Continuous Measurement Reading of Continuous Measurement API. */ /** \defgroup DXS_GR909 GR-909 Network Line Testing GR-909 Line Testing configuration and control API. */ /** \defgroup DXS_CALIBRATION Calibration Analog Line Calibration and Open Loop Calibration control API. */ /** \defgroup DXS_HOOK_STATE_MACHINE Hook State Machine Hook State Machine configuration API. */ /** \defgroup DXS_CAPACITANCE_MEASUREMENTS Capacitance Measurement Capacitance Measurement API. */ /** \defgroup DXS_ACLM AC Level Meter Measurement AC Level Meter measurement control API. */ /** \defgroup DXS_GPIO_PIN_CONTROL GPIO Pin Control Interface GPIO/IO pin handling API. */ /** \defgroup DXS_CLOCK_FAILURE_HANDLING Clock Failure Handling PCM clock failure handling. */ /** \defgroup DXS_MULTI_CHANNEL_SHARED_HW Shared DC/DC converter Shared DC/DC converter configuration API. */ /** \defgroup DXS_EVENT_REPORTING Event Reporting Event reporting API. */ /*@}*/ /* DXS_API */ /* ========================================================================== */ /* Type definitions */ /* ========================================================================== */ /** Definitions for line feeding. */ typedef enum { /** Set operating mode to power down. */ DXS_LINE_FEED_DISABLED = 0, /** Set operating mode to ringing mode with normal polarity. */ DXS_LINE_FEED_RING_BURST = 1, /** Set operating mode to standby mode. */ DXS_LINE_FEED_STANDBY = 2, /** Set operating mode to active with normal polarity. Normal polarity means that the ring wire is near VBAT and the tip wire is near GND. */ DXS_LINE_FEED_ACTIVE = 3, /** Set operating mode to ground start mode. */ DXS_LINE_FEED_GROUND_START = 5, /** Set operating mode to calibration. */ DXS_LINE_FEED_CALIBRATE = 6, /** Set operating mode to GR909 linetesting. */ DXS_LINE_FEED_GR909 = 7, /** Set mode to active with normal polarity and message waiting indication. This operating mode is only available if the subscriber is on-hook. */ DXS_LINE_FEED_ACTIVE_MWI = 12, /** Send howler tone with normal polarity settings. Sending of a howler tone requires a special setup (due to high amplitude). This operating mode is only available if the subscriber is off-hook. */ DXS_LINE_FEED_ACTIVE_HOWL = 13, /** Set operating mode to ringing with reverse polarity. */ DXS_LINE_FEED_RINGING_REVPOL = 17, /** Set operating mode to active reverse polarity. Reverse polarity means that the tip wire is near VBAT and the ring wire is near GND. */ DXS_LINE_FEED_ACTIVE_REVPOL = 19, /** Set operating mode to ground start tip to ground. */ DXS_LINE_FEED_GROUND_START_T2G = 21, /** Set operating mode to capacitance linetesting measurement. */ DXS_LINE_FEED_CAP_MEAS = 23, /** Send howler tone with reverse polarity settings. Sending of a howler tone requires a special setup (due to high amplitude). This operating mode is only available in ACT off-hook. */ DXS_LINE_FEED_ACTIVE_HOWL_REVPOL = 29 } DXS_LINE_MODE_t; /** This structure contains data specific to the DTMF event. */ typedef struct { /** DTMF digit number information. - 0: No_Key, no key detected - 11: Key_0, DTMF key '0' detected - 1: Key_1, DTMF key '1' detected - 2: Key_2, DTMF key '2' detected - 3: Key_3, DTMF key '3' detected - 4: Key_4, DTMF key '4' detected - 5: Key_5, DTMF key '5' detected - 6: Key_6, DTMF key '6' detected - 7: Key_7, DTMF key '7' detected - 8: Key_8, DTMF key '8' detected - 9: Key_9, DTMF key '9' detected - 10: Key_*, DTMF key '*' detected - 12: Key_#, DTMF key '#' detected - 28: Key_A, DTMF key 'A' detected - 29: Key_B, DTMF key 'B' detected - 30: Key_C, DTMF key 'C' detected - 31: Key_D, DTMF key 'D' detected */ uint8_t digit; /** DTMF digit in ASCII representation. - 0: No_Key, no key detected - 48: Key_0, DTMF key '0' detected - 49: Key_1, DTMF key '1' detected - 50: Key_2, DTMF key '2' detected - 51: Key_3, DTMF key '3' detected - 52: Key_4, DTMF key '4' detected - 53: Key_5, DTMF key '5' detected - 54: Key_6, DTMF key '6' detected - 55: Key_7, DTMF key '7' detected - 56: Key_8, DTMF key '8' detected - 57: Key_9, DTMF key '9' detected - 42: Key_*, DTMF key '*' detected - 35: Key_#, DTMF key '#' detected - 65: Key_A, DTMF key 'A' detected - 66: Key_B, DTMF key 'B' detected - 67: Key_C, DTMF key 'C' detected - 68: Key_D, DTMF key 'D' detected */ char ascii; } DXS_EVENT_DATA_DTMF_t; /** Definitions for the events. */ typedef enum { DXS_EVENT_NONE = 0, /** Hook event: on-hook. */ DXS_EVENT_FXS_ONHOOK = 1, /** Hook event: off-hook. */ DXS_EVENT_FXS_OFFHOOK = 2, /** Hook event: flash hook. */ DXS_EVENT_FXS_FLASH = 3, /** Line testing finished (results are ready, where applicable). */ DXS_EVENT_NLT_END = 4, /** Line testing aborted. */ DXS_EVENT_NLT_ABORT = 5, /** Pulse digit detected. */ DXS_EVENT_PULSE_DIGIT = 6, /** Indicates start of pulse dialing. This event can be used to stop the dial tone. */ DXS_EVENT_PULSE_START = 7, /** DTMF tone detected. */ DXS_EVENT_DTMF_DIGIT = 8, /** End of calibration. The calibration process has finished or was stopped because of an error. */ DXS_EVENT_CALIBRATION_END = 9, /** End of metering pulse. */ DXS_EVENT_METERING_END = 10, /** Over temperature detected. */ DXS_EVENT_OVERTEMP = 11, /** Over temperature finished. */ DXS_EVENT_OVERTEMP_END = 12, /** Ground fault detected. */ DXS_EVENT_GROUND_FAULT = 13, /** Ground fault finished. */ DXS_EVENT_GROUND_FAULT_END = 14, /** Call progress tone detected. */ DXS_EVENT_TONE_DET_CPT = 15, /** Call progress tone detection ended. */ DXS_EVENT_TONE_DET_CPT_END = 16, /** Debug command error event. */ DXS_EVENT_DEBUG_CERR = 17, /** Caller ID sender request data. */ DXS_EVENT_CID_REQ_DATA = 18, /** Caller ID buffer underflow. */ DXS_EVENT_CID_BUF_UNDERFLOW = 19, /** Caller ID sending finished. */ DXS_EVENT_CID_END = 20, /** Caller ID sequence finished. */ DXS_EVENT_CID_SEQ_END = 21, /** Caller ID sequence aborted. */ DXS_EVENT_CID_SEQ_ERROR = 22, /** Ground key detected. */ DXS_EVENT_GROUND_KEY = 23, /** Ground key finished. */ DXS_EVENT_GROUND_KEY_END = 24, /** Firmware watchdog (crash). The application must reinitialize the device upon reception of this event. */ DXS_EVENT_FAULT_FW_WATCHDOG = 25, /* Timeout event */ DXS_EVENT_T2G_TIMER_EXPIRED = 26, /** Raw hook event: on-hook. */ DXS_EVENT_FXS_RAW_ONHOOK = 27, /** Raw hook event: off-hook. */ DXS_EVENT_FXS_RAW_OFFHOOK = 28, /* ATTENTION: if DXS_EVENT_MAX exceeds 63 due to adding new events, the event_mask in DXS_CHANNEL_t has to be extended */ DXS_EVENT_MAX = 63 } DXS_Event_id_t; 解析
08-26
#include <platform.h> #include <sys_app.h> #include <subghz_phy_app.h> #include <radio.h> #include <string.h> /* USER CODE BEGIN Includes */ #include <stm32_timer.h> #include <stm32_seq.h> #include <utilities_def.h> #include <app_version.h> #include <subghz_phy_version.h> /* USER CODE END Includes */ /* External variables ---------------------------------------------------------*/ /* USER CODE BEGIN EV */ /* USER CODE END EV */ /* Private typedef -----------------------------------------------------------*/ void MX_SPI2_Init(void); void ADS1120reset(void); uint16_t ADS1120readonce(void); /* USER CODE BEGIN PTD */ #include <stdio.h> #include <math.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define SAMPLES_TO_COLLECT 10 static int16_t calibrated_samples[SAMPLES_TO_COLLECT][3]; static uint8_t sample_index = 0; static uint8_t prediction_results[SAMPLES_TO_COLLECT] = {0}; typedef struct Vector { double x, y, z; }Vector1; const Vector1 a_static = { 9.8 / 1.414, 0, 9.8 / 1.414 }; //void cc(Vector1 a_static) //{ // a_static.x=g/sqrt(2); // a_static.y=0; // a_static.z=g/sqrt(2); //} //Vector1 a_static; // cc(*a_static); void normalize(Vector1 *v) // ¸ÄΪָÕë´«µÝ { double l = sqrt(v->x*v->x + v->y*v->y + v->z*v->z); v->x /= l; v->y /= l; v->z /= l; } Vector1 cross(Vector1 a, Vector1 b) { Vector1 result; result.x = a.y * b.z - a.z * b.y; result.y = a.z * b.x - a.x * b.z; result.z = a.x * b.y - a.y * b.x; return result; } Vector1 Convert(double R[3][3], Vector1 a_device) { Vector1 a_world; a_world.x = R[0][0] * a_device.x + R[1][0] * a_device.y + R[2][0] * a_device.z; a_world.y = R[0][1] * a_device.x + R[1][1] * a_device.y + R[2][1] * a_device.z; a_world.z = R[0][2] * a_device.x + R[1][2] * a_device.y + R[2][2] * a_device.z; return a_world; } Vector1 Remove(Vector1 a_world, double g) { Vector1 a_motion; a_motion.x = a_world.x/100; a_motion.y = a_world.y/100; a_motion.z = (a_world.z - g)/100; return a_motion; } Vector1 processBufferTx(uint8_t *BufferTx) { Vector1 res = { 0, 0, 0 }; for (int rain = 0; rain < 10; rain++) { int ax_sign = BufferTx[5 + 6 * rain] ? -1 : 1; int ax_value = BufferTx[6 + 6 * rain]; double ax = ax_sign * (ax_value * 100.0); int ay_sign = BufferTx[7 + 6 * rain] ? -1 : 1; int ay_value = BufferTx[8 + 6 * rain]; double ay = ay_sign * (ay_value * 100.0); int az_sign = BufferTx[9 + 6 * rain] ? -1 : 1; int az_value = BufferTx[10 + 6 * rain]; double az = az_sign * (az_value * 100.0); ax = ax / 4.0 * 0.976; ay = ay / 4.0 * 0.976; az = az / 4.0 * 0.976; res.x += ax; res.y += ay; res.z += az; } res.x /= 10; res.y /= 10; res.z /= 10; return res; } Vector1 solve(Vector1 raw_data) { static Vector1 a_static = {9.8/1.414, 0, 9.8/1.414}; normalize(&a_static); /* ×ø±êϵת»» */ Vector1 t = { 1, 0, 0 }; Vector1 x_temp = cross(t, a_static); normalize(&x_temp); Vector1 y = cross(a_static, x_temp); normalize(&y); double R[3][3] = { {x_temp.x, y.x, a_static.x}, {x_temp.y, y.y, a_static.y}, {x_temp.z, y.z, a_static.z} }; /* ×ø±êת»» */ Vector1 a_world = Convert(R, raw_data); /* È¥³ýÖØÁ¦Ó°Ïì */ return Remove(a_world, 9.8); } #define MAX_DATA_POINTS 200 // ѵÁ·¼¯´óС #define INPUT_FEATURE_DIM 3 // Ñù±¾Î¬¶È /* ½á¹¹Ìå */ /* ѵÁ·Êý¾Ý½á¹¹Ìå */ typedef struct { int16_t f[3]; // ÌØÕ÷Êý×é uint8_t label; // ±êÇ© } DataPoint; /* È«¾ÖѵÁ·Êý¾Ý¼¯£¨ÒÑÔ¤ÖÃ50¸öÑù±¾£© */ DataPoint dataset[MAX_DATA_POINTS] = { {{35, -13, -9}, 1},{{37, -13, -11}, 1},{{35, -9, -19}, 1},{{36, -8, -18}, 1}, {{37, -5, -18}, 1},{{37, -11, -23}, 1},{{36, -7, -17}, 1},{{36, -6, -15}, 1}, {{36, -9, -12}, 1},{{35, -9, -12}, 1},{{35, -8, -11}, 1}, {{34, -8, -11}, 1},{{35, -16, -6}, 1},{{35, -16, -5}, 1}, {{36, -17, -6}, 1},{{35, -17, -6}, 1},{{35, -18, -7}, 1}, {{36, -18, -6}, 1},{{36, -18, -6}, 1},{{36, -18, -6}, 1}, {{36, -17, -4}, 1},{{37, -16, -3}, 1},{{37, -23, -6}, 1}, {{37, -23, -6}, 1},{{37, -18, 0}, 1},{{37, -18, -1}, 1}, {{38, -18, -1}, 1},{{38, -18, -1}, 1},{{38, -8, -11}, 1}, {{38, -9, -12}, 1},{{38, -9, -12}, 1},{{26, -8, -11}, 1}, {{25, -20, 0}, 1},{{25, -20, 0}, 1},{{29, -19, 1}, 1}, {{28, -20, 0}, 1},{{30, -19, 1}, 1},{{29, -19, -1}, 1}, {{19, -23, -4}, 0},{{18, -23, -5}, 0},{{15, -14, -6}, 0}, {{20, -23, -11}, 0},{{19, -27, -17}, 0},{{20, -20, -10}, 0}, {{26, -15, -2}, 0},{{27, -16, -3}, 0},{{27, -15, -2}, 0}, {{28, -16, -3}, 0},{{27, -15, -3}, 0},{{27, -16, -3}, 0}, {{26, -8, -11}, 0},{{25, -8, -11}, 0},{{27, -8, -11}, 0}, {{27, -8, -11}, 0},{{3, -14, -1}, 0},{{4, -14, 0}, 0}, {{25, -8, -11}, 0},{{27, -8, -11}, 0},{{27, -26, 8}, 0}, {{3, -24, 9}, 0},{{4, -24, 10}, 0},{{3, -24, 10}, 0}, {{4, -24, 10}, 0},{{3, -23, 10}, 0},{{4, -23, 10}, 0}, {{7, -23, 10}, 0},{{4, -23, 9}, 0},{{4, -23, 9}, 0}, {{4, -23, 11}, 0},{{0, -25, 10}, 0},{{0, -25, 9}, 0}, {{0, -27, 9}, 1},{{28, -26, 12}, 2},{{30, -27, 10}, 2}, {{30, -27, 10}, 2},{{29, -27, 10}, 2},{{29, -28, 9}, 2}, {{29, -28, 9}, 2},{{28, -28, 9}, 2},{{28, -28, 7}, 2}, {{26, -29, 8}, 2},{{27, -28, 7}, 2},{{26, -40, -4}, 2}, {{23, -40, -4}, 2},{{26, -38, -4}, 2},{{24, -39, -5}, 2}, {{25, -37, -3}, 2},{{-1, -40, -4}, 2},{{17, -29, 6}, 2}, {{20, -29, 8}, 2},{{20, -28, 8}, 2},{{17, -28, 7}, 2}, {{18, -29, 6}, 2},{{19, -30, 6}, 2},{{22, -29, 6}, 2}, {{20, -28, 6}, 2},{{21, -28, 4}, 2},{{23, -27, 6}, 2}, {{19, -27, 6}, 2},{{20, -28, 5}, 2},{{18, -28, 5}, 2}, {{22, -30, 2}, 2},{{23, -34, -1}, 2},{{11, -27, 6}, 2}, {{16, -29, 5}, 2},{{16, -33, 1}, 2},{{28, -28, 7}, 2}, {{28, -28, 6}, 2},{{27, -28, 7}, 2},{{28, -28, 7}, 2},{{26, -29, 6}, 2}, {{25, -28, 6}, 2},{{27, -29, 6}, 2},{{28, -30, 6}, 2}, {{29, -28, 6}, 2},{{31, -28, 6}, 2},{{26, -37, -3}, 2}, {{22, -38, -4}, 2},{{22, -35, -1}, 2},{{21, -40, -6}, 2}, {{27, -25, 8}, 2},{{28, -24, 9}, 2},{{27, -25, 7}, 2}, {{30, -25, 7}, 2},{{31, -25, 7}, 2},{{30, -27, 9}, 2}, {{30, -28, 8}, 2},{{30, -29, 6}, 2},{{29, -27, 9}, 2}, {{30, -25, 11}, 2},{{30, -23, 11}, 2},{{28, -25, 11}, 2}, {{26, -25, 9}, 2},{{20, -37, -1}, 2},{{16, -39, -2}, 2}, {{9, -38, -3}, 2},{{13, -38, -3}, 2},{{12, -37, -2}, 2}, {{-10, -37, -2}, 2},{{0, -30, 4}, 2},{{10, -27, 9}, 2}, {{9, -26, 8}, 2},{{9, -27, 9}, 2},{{12, -27, 9}, 2}, {{14, -26, 8}, 2},{{16, -26, 9}, 2},{{13, -25, 10}, 2},{{15, -25, 11}, 2}, {{16, -25, 11}, 2},{{17, -25, 11}, 2},{{16, -25, 11}, 2}, {{13, -26, 9}, 2},{{15, -27, 9}, 2},{{22, -29, 6}, 2}, {{23, -29, 6}, 2},{{24, -28, 6}, 2},{{24, -26, 5}, 2}, {{25, -26, 6}, 2},{{25, -25, 7}, 2},{{24, -26, 8}, 2}, {{25, -26, 6}, 2},{{25, -25, 7}, 2},{{23, -26, 8}, 2}, {{3, -28, 5}, 2},{{3, -28, 6}, 2},{{1, -29, 6}, 2}, {{2, -30, 6}, 2},{{3, -30, 4}, 2},{{25, -21, 4}, 2}, {{25, -21, 4}, 2},{{25, -21, 4}, 2},{{26, -21, 5}, 2}, {{25, -21, 6}, 2},{{26, -21, 4}, 2},{{32, -11, 14}, 2}, {{32, -11, 14}, 2},{{32, -11, 15}, 2},{{32, -10, 16}, 2}, {{20, 3, 27}, 2},{{19, 5, 29}, 2},{{13, 7, 31}, 2}, {{-5, -6, 16}, 2},{{-6, -13, 9}, 2},{{4, -4, 21}, 2}, {{11, -23, 1}, 2},{{9, -23, 1}, 2},{{9, -23, 0}, 2}, {{10, -23, 1}, 2},{{11, -23, 0}, 2}, {{7, -23, 0}, 2},{{8, -24, -1}, 2},{{10, -24, -1}, 2}, {{10, -23, -1}, 2},{{11, -23, 0}, 2},{{37, -17, 6}, 2}, {{36, -18, 5}, 2},{{34, -17, 6}, 2},{{35, -18, 5}, 2}, {{35, -17, 7}, 2},{{34, -17, 7}, 2},{{35, -18, 6}, 2}, {{36, -17, 6}, 2},{{34, -17, 6}, 2},{{35, -16, 6}, 2}, {{34, 7, -23}, 3},{{33, 1, -23}, 3},{{30, -5, -29}, 3}, {{22, -9, -32}, 3},{{16, -6, -30}, 3},{{22, -10, -34}, 3},{{12, 0, -23}, 3}, {{14, -7, -28}, 3},{{11, -3, -24}, 3},{{13, 2, -16}, 3}, {{27, -20, 6}, 3},{{28, -21, 6}, 3},{{27, -21, 5}, 3}, {{27, -21, 5}, 3},{{27, -19, 4}, 3},{{26, -21, 4}, 3}, {{26, -22, 4}, 3},{{25, -25, 5}, 3},{{25, -26, 4}, 3}, {{22, -33, -2}, 3},{{9, -38, 2}, 3},{{12, -34, 6}, 3},{{18, -23, 2}, 3}, {{17, -22, 1}, 3},{{19, -20, 0}, 3},{{20, -21, 0}, 3}, {{21, -21, 2}, 3},{{20, -21, 2}, 3},{{20, -21, 2}, 3}, {{20, -21, 1}, 3},{{22, -20, 2}, 3},{{23, -23, 3}, 3}, {{23, -10, -15}, 3},{{23, -16, -23}, 3},{{19, -17, -24}, 3}, {{9, -14, -21}, 3},{{18, -21, -27}, 3},{{15, -14, -20}, 3},{{18, -20, -23}, 3}, {{-1, -5, -8}, 3},{{9, -5, -8}, 3},{{8, -4, -7}, 3} }; float train_mean[3] = {0}; float train_std[3] = {0}; void compute_train_stats(void); float euclidean_distance(const float *a, const float *b); uint8_t predict_class(const int16_t *features); void test_knn_performance(void); float euclidean_distance(const float *a, const float *b) { return sqrt(pow(a[0]-b[0],2) + pow(a[1]-b[1],2) + pow(a[2]-b[2],2)); } void compute_train_stats() { // ¼ÆËã¾ùÖµ float sum[3] = {0}; for (int i = 0; i < MAX_DATA_POINTS; i++) { sum[0] += dataset[i].f[0]; sum[1] += dataset[i].f[1]; sum[2] += dataset[i].f[2]; } train_mean[0] = sum[0] / MAX_DATA_POINTS; train_mean[1] = sum[1] / MAX_DATA_POINTS; train_mean[2] = sum[2] / MAX_DATA_POINTS; // ¼ÆËã±ê×¼²î float variance[3] = {0}; for (int i = 0; i < MAX_DATA_POINTS; i++) { variance[0] += pow(dataset[i].f[0] - train_mean[0], 2); variance[1] += pow(dataset[i].f[1] - train_mean[1], 2); variance[2] += pow(dataset[i].f[2] - train_mean[2], 2); } for (int j = 0; j < 3; j++) { train_std[j] = sqrt(variance[j]/MAX_DATA_POINTS); if (train_std[j] < 1e-5) train_std[j] = 1e-5; // ·ÀÖ¹³ýÁã } } /* KNNÔ¤²âʵÏÖ£¨k=10£© */ uint8_t predict_class(const int16_t *features) { float normalized_input[3]; // ÊäÈëÌØÕ÷¹éÒ»»¯ for (int j=0; j<3; j++) { normalized_input[j] = (features[j]-train_mean[j])/train_std[j]; } // ´æ´¢¾àÀëºÍ±êÇ© float distances[MAX_DATA_POINTS]; uint8_t labels[MAX_DATA_POINTS]; const uint8_t k = 7; // ¾­ÊµÑéµ÷ÕûµÄ×î¼ÑkÖµ // ¼ÆËãËùÓоàÀë for (int i=0; i<MAX_DATA_POINTS; i++) { float normalized_train[3]; for (int j=0; j<3; j++) { normalized_train[j] = (dataset[i].f[j]-train_mean[j])/train_std[j]; } distances[i] = euclidean_distance(normalized_input, normalized_train); labels[i] = dataset[i].label; } // ÕÒ³ök¸ö×î½üÁÚ for (int i=0; i<k; i++) { int min_idx = i; for (int j=i+1; j<MAX_DATA_POINTS; j++) { if (distances[j] < distances[min_idx]) min_idx = j; } // ½»»»Î»Öà float tmp_d = distances[i]; distances[i] = distances[min_idx]; distances[min_idx] = tmp_d; uint8_t tmp_l = labels[i]; labels[i] = labels[min_idx]; labels[min_idx] = tmp_l; } // ¼ÓȨͶƱ£¨Ê¹ÓþàÀëµ¹Êý×÷ÎªÈ¨ÖØ£© float weight_sum[4] = {0}; for (int i=0; i<k; i++) { weight_sum[labels[i]] += 1/(distances[i]+1e-5); // ·ÀÖ¹³ýÁã } // È·¶¨×îÖÕÀà±ð uint8_t predicted = 0; float max_weight = 0; for (int i=0; i<4; i++) { if (weight_sum[i] > max_weight) { max_weight = weight_sum[i]; predicted = i; } } printf("predicted label: %d\n", predicted); return predicted; } /* USER CODE END EV */ int * features; /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ typedef enum { S_IDLE, S_RX, S_RX_TIMEOUT, S_RX_ERROR, S_TX, S_TXing, S_TX_TIMEOUT, S_SEND_DATA, } States_t; /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* Configurations */ /*Timeout*/ #define RX_TIMEOUT_VALUE 5000 #define TX_TIMEOUT_VALUE 10000 //???? #define SEND_PERIOD_MS 15000 //??ID #define LOCAL_ID 0x01 //??ID #define REMOTE_ID 0x10 //???? #define DATA_TYPE 0x01 /*Size of the payload to be sent*/ /* Size must be greater of equal the PING and PONG*/ #define MAX_APP_BUFFER_SIZE 255 #if (PAYLOAD_LEN > MAX_APP_BUFFER_SIZE) #error PAYLOAD_LEN must be less or equal than MAX_APP_BUFFER_SIZE #endif /* (PAYLOAD_LEN > MAX_APP_BUFFER_SIZE) */ /*????*/ /*SHT3x??*/ #define SHT3x_ADDRESS 0x44<<1 //?????7?,?????? #define SCL_Pin GPIO_PIN_15 #define SCL_GPIO_Port GPIOB #define SDA_Pin GPIO_PIN_9 #define SDA_GPIO_Port GPIOB #define SHT3x_W_SCL(x) HAL_GPIO_WritePin(GPIOB, SCL_Pin, (GPIO_PinState)(x)) #define SHT3x_W_SDA(x) HAL_GPIO_WritePin(GPIOB, SDA_Pin, (GPIO_PinState)(x)) #define SHT3x_R_SDA() HAL_GPIO_ReadPin(GPIOB, SDA_Pin) #define SHT3x_R_SCL() HAL_GPIO_ReadPin(GPIOB, SCL_Pin) /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /*??????*/ void SHT3x_I2C_START(){ SHT3x_W_SDA(1); SHT3x_W_SCL(1); HAL_Delay(1); SHT3x_W_SDA(0); HAL_Delay(1); SHT3x_W_SCL(0); HAL_Delay(1); } /*??????*/ void SHT3x_I2C_STOP(){ SHT3x_W_SDA(0); SHT3x_W_SCL(1); HAL_Delay(1); SHT3x_W_SDA(1); HAL_Delay(1); } /** * @brief ?????? * @param ? * @retval 1-?????,0-???? */ uint8_t WaitAck(void) { uint8_t ret; SHT3x_W_SCL(1); HAL_Delay(1); if(SHT3x_R_SDA()){ ret=1; } else{ ret=0; } SHT3x_W_SCL(0); HAL_Delay(1); return ret; } /** * @brief I2C?????? * @param Byte ???????? * @retval ? */ void SHT3x_I2C_SendByte(uint8_t Byte) { uint8_t i; for (i = 0; i < 8; i++) { SHT3x_W_SDA((Byte<<i) & 0x80 ); SHT3x_W_SCL(1); HAL_Delay(1); SHT3x_W_SCL(0); HAL_Delay(1); } SHT3x_W_SDA(1);//??SDA?? } /** * @brief ???????? * @param MSB ?8? * @param LSB ?8? * @retval ? */ void SHT3x_WriteByte(uint8_t MSB,uint8_t LSB) { SHT3x_I2C_START(); //?????? SHT3x_I2C_SendByte(SHT3x_ADDRESS); //??????? WaitAck(); SHT3x_I2C_SendByte(MSB);//???8??? WaitAck(); SHT3x_I2C_SendByte(LSB);//???8??? WaitAck(); SHT3x_I2C_STOP(); } /** * @brief I2C?????? * @param NACK 1-?????,0-???? * @retval ???????? */ uint8_t SHT3x_ReadData(uint8_t NACK) { uint8_t i,Byte=0; SHT3x_W_SDA(1);//??SDA?? for (i = 0; i < 8; i++) { SHT3x_W_SCL(1); HAL_Delay(1); Byte=Byte|(SHT3x_R_SDA()<<(7-i)); HAL_Delay(1); SHT3x_W_SCL(0); HAL_Delay(1); } SHT3x_W_SDA(NACK);//????/????? SHT3x_W_SCL(1); HAL_Delay(1); SHT3x_W_SCL(0); HAL_Delay(1); SHT3x_W_SDA(1);//??SDA?? return Byte; } /*????SHT3x*/ void SHT3x_SoftReset(void) { SHT3x_WriteByte(0x30,0xA2); //?????SHT3x } /*?????*/ void SHT3x_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, SCL_Pin | SDA_Pin, GPIO_PIN_SET); /*Configure GPIO pins : PBPin PBPin */ GPIO_InitStruct.Pin = SCL_Pin | SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); SHT3x_W_SCL(1); SHT3x_W_SDA(1); // SHT3x_WriteByte(0X27,0X21); //????????(??10?,Medium Repeatability) HAL_Delay(1); } #define SCL1_Pin GPIO_PIN_4 #define SCL1_GPIO_Port GPIOA #define SDA1_Pin GPIO_PIN_15 #define SDA1_GPIO_Port GPIOA #define SHT3x1_W_SCL(x) HAL_GPIO_WritePin(GPIOA, SCL1_Pin, (GPIO_PinState)(x)) #define SHT3x1_W_SDA(x) HAL_GPIO_WritePin(GPIOA, SDA1_Pin, (GPIO_PinState)(x)) #define SHT3x1_R_SDA() HAL_GPIO_ReadPin(GPIOA, SDA1_Pin) #define SHT3x1_R_SCL() HAL_GPIO_ReadPin(GPIOA, SCL1_Pin) /* USER CODE END EF */ void MyI2C_W_SCL(uint8_t BitValue) { SHT3x1_W_SCL(BitValue); HAL_Delay(1); } void MyI2C_W_SDA(uint8_t BitValue) { SHT3x1_W_SDA(BitValue); HAL_Delay(1); } uint8_t MyI2C_R_SDA(void) { uint8_t BitValue; BitValue = SHT3x1_R_SDA(); HAL_Delay(1); return BitValue; } void MyI2C_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, SCL1_Pin | SDA1_Pin, GPIO_PIN_SET); /*Configure GPIO pins : PBPin PBPin */ GPIO_InitStruct.Pin = SCL1_Pin | SDA1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // GPIO_InitStruct.Pin = GPIO_PIN_5; // GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } void MyI2C_Start(void) { MyI2C_W_SDA(1); MyI2C_W_SCL(1); MyI2C_W_SDA(0); MyI2C_W_SCL(0); } void MyI2C_Stop(void) { MyI2C_W_SDA(0); MyI2C_W_SCL(1); MyI2C_W_SDA(1); } void MyI2C_SendByte(uint8_t Byte) { uint8_t i; for (i = 0; i < 8; i ++) { MyI2C_W_SDA(Byte & (0x80 >> i)); MyI2C_W_SCL(1); MyI2C_W_SCL(0); } } uint8_t MyI2C_ReceiveByte(void) { uint8_t i, Byte = 0x00; MyI2C_W_SDA(1); for (i = 0; i < 8; i ++) { MyI2C_W_SCL(1); if (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);} MyI2C_W_SCL(0); } return Byte; } void MyI2C_SendAck(uint8_t AckBit) { MyI2C_W_SDA(AckBit); MyI2C_W_SCL(1); MyI2C_W_SCL(0); } uint8_t MyI2C_ReceiveAck(void) { uint8_t AckBit; MyI2C_W_SDA(1); MyI2C_W_SCL(1); AckBit = MyI2C_R_SDA(); MyI2C_W_SCL(0); return AckBit; } #define MPU6050_ADDRESS 0x32 void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data) { MyI2C_Start(); MyI2C_SendByte(MPU6050_ADDRESS); MyI2C_ReceiveAck(); MyI2C_SendByte(RegAddress); MyI2C_ReceiveAck(); MyI2C_SendByte(Data); MyI2C_ReceiveAck(); MyI2C_Stop(); } uint8_t MPU6050_ReadReg(uint8_t RegAddress) { uint8_t Data; MyI2C_Start(); MyI2C_SendByte(MPU6050_ADDRESS); MyI2C_ReceiveAck(); MyI2C_SendByte(RegAddress); MyI2C_ReceiveAck(); MyI2C_Start(); MyI2C_SendByte(MPU6050_ADDRESS | 0x01); MyI2C_ReceiveAck(); Data = MyI2C_ReceiveByte(); MyI2C_SendAck(1); MyI2C_Stop(); return Data; } #define MPU6050_PWR_MGMT_1 0x20 #define MPU6050_PWR_MGMT_2 0x25 #define MPU6050_SMPLRT_DIV 0x23 void MPU6050_Init(void) { MyI2C_Init(); MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x60); MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x84); MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x00); } #define MPU6050_ACCEL_XOUT_H 0x29 #define MPU6050_ACCEL_XOUT_L 0x28 #define MPU6050_ACCEL_YOUT_H 0x2B #define MPU6050_ACCEL_YOUT_L 0x2A #define MPU6050_ACCEL_ZOUT_H 0x2D #define MPU6050_ACCEL_ZOUT_L 0x2C void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ) { uint8_t DataH, DataL; DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L); *AccX = (DataH << 8) | DataL; DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L); *AccY = (DataH << 8) | DataL; DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H); DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L); *AccZ = (DataH << 8) | DataL; } /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* Radio events function pointer */ static RadioEvents_t RadioEvents; /* USER CODE BEGIN PV */ /*Ping Pong FSM states */ static States_t State = S_IDLE; /* App Rx Buffer*/ static uint8_t BufferRx[MAX_APP_BUFFER_SIZE]; /* App Tx Buffer*/ static uint8_t BufferTx[MAX_APP_BUFFER_SIZE]; /* Last Received Buffer Size*/ uint16_t RxBufferSize = 0; /* Last Received packer Rssi*/ int8_t RssiValue = 0; /* Last Received packer SNR (in Lora modulation)*/ int8_t SnrValue = 0; /* Led Timers objects*/ //????? static UTIL_TIMER_Object_t timerSendData; /* random delay to make sure 2 devices will sync*/ /* the closest the random delays are, the longer it will take for the devices to sync when started simultaneously*/ static int32_t random_delay; //???? static int16_t temp_v=0; static uint16_t bat_v=0; static uint16_t pa11_v=0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ /*! * @brief Function to be executed on Radio Tx Done event */ static void OnTxDone(void); /** * @brief Function to be executed on Radio Rx Done event * @param payload ptr of buffer received * @param size buffer size * @param rssi * @param LoraSnr_FskCfo */ static void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t LoraSnr_FskCfo); /** * @brief Function executed on Radio Tx Timeout event */ static void OnTxTimeout(void); /** * @brief Function executed on Radio Rx Timeout event */ static void OnRxTimeout(void); /** * @brief Function executed on Radio Rx Error event */ static void OnRxError(void); /* USER CODE BEGIN PFP */ /** * @brief Function executed on when led timer elapses * @param context ptr of LED context */ static void OnSendDataEvent(void *context); /** * @brief PingPong state machine implementation */ static void SendData_Process(void); static char ReadSHT3x(float *Hum,float *Temp); static uint8_t SHT3x_CRC_CAL(uint16_t DAT); /* USER CODE END PFP */ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { switch (GPIO_Pin) { case 1: /* Note: when "EventType == TX_ON_TIMER" this GPIO is not initialized */ APP_LOG(TS_OFF, VLEVEL_M, "\n\rBUT1 Event\n\r"); break; default: break; } } /* Exported functions ---------------------------------------------------------*/ void SubghzApp_Init(void) { /* USER CODE BEGIN SubghzApp_Init_1 */ /* Print APP version*/ /*???????*/ UTIL_TIMER_Create(&timerSendData, 0xFFFFFFFFU, UTIL_TIMER_ONESHOT, OnSendDataEvent, NULL); /*??????*/ UTIL_TIMER_SetPeriod(&timerSendData, SEND_PERIOD_MS); /*????*/ UTIL_TIMER_Start(&timerSendData); /* USER CODE END SubghzApp_Init_1 */ /* Radio initialization */ RadioEvents.TxDone = OnTxDone; RadioEvents.RxDone = OnRxDone; RadioEvents.TxTimeout = OnTxTimeout; RadioEvents.RxTimeout = OnRxTimeout; RadioEvents.RxError = OnRxError; /*?????*/ Radio.Init(&RadioEvents); /*??????*/ Radio.SetChannel(RF_FREQUENCY); /* Radio configuration */ APP_LOG(TS_OFF, VLEVEL_M, "---------------\n\r"); APP_LOG(TS_OFF, VLEVEL_M, "LORA_MODULATION\n\r"); APP_LOG(TS_OFF, VLEVEL_M, "LORA_BW=%d kHz\n\r", (1 << LORA_BANDWIDTH) * 125); APP_LOG(TS_OFF, VLEVEL_M, "LORA_SF=%d\n\r", LORA_SPREADING_FACTOR); /*??????*/ Radio.SetTxConfig(MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, true, 0, 0, LORA_IQ_INVERSION_ON, TX_TIMEOUT_VALUE); /*??????*/ Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0, true, 0, 0, LORA_IQ_INVERSION_ON, true); /*????????*/ Radio.SetMaxPayloadLength(MODEM_LORA, MAX_APP_BUFFER_SIZE); /* LED initialization*/ compute_train_stats(); /* ?? initialization*/ BSP_PB_Init(BUTTON_SW1, BUTTON_MODE_EXTI); /*calculate random delay for synchronization*/ random_delay = (Radio.Random()) >> 22; /*10bits random e.g. from 0 to 1023 ms*/ /*fills tx buffer*/ memset(BufferTx, 0x0, MAX_APP_BUFFER_SIZE); APP_LOG(TS_ON, VLEVEL_L, "rand=%d\n\r", random_delay); /*starts reception*/ //Radio.Rx(RX_TIMEOUT_VALUE + random_delay); /*register task to to be run in while(1) after Radio IT*/ /* ????*/ UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), UTIL_SEQ_RFU, SendData_Process); /* USER CODE END SubghzApp_Init_2 */ } /* USER CODE BEGIN EF */ /* USER CODE END EF */ /* Private functions ---------------------------------------------------------*/ /* ??????*/ static void OnTxDone(void) { /* USER CODE BEGIN OnTxDone */ /* Update the State of the FSM*/ State = S_TX; /* Run PingPong process in background*/ UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0); /* USER CODE END OnTxDone */ } /* ??????*/ static void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t LoraSnr_FskCfo) { /* USER CODE BEGIN OnRxDone */ APP_LOG(TS_ON, VLEVEL_L, "OnRxDone\n\r"); APP_LOG(TS_ON, VLEVEL_L, "RssiValue=%d dBm, SnrValue=%ddB\n\r", rssi, LoraSnr_FskCfo); /* Update the State of the FSM*/ State = S_RX; /* Clear BufferRx*/ memset(BufferRx, 0, MAX_APP_BUFFER_SIZE); /* Record payload size*/ RxBufferSize = size; if (RxBufferSize <= MAX_APP_BUFFER_SIZE) { memcpy(BufferRx, payload, RxBufferSize); } /* Record Received Signal Strength*/ RssiValue = rssi; /* Record payload content*/ APP_LOG(TS_ON, VLEVEL_H, "payload. size=%d \n\r", size); for (int i = 0; i < PAYLOAD_LEN; i++) { APP_LOG(TS_OFF, VLEVEL_H, "%02X", BufferRx[i]); if (i % 16 == 15) { APP_LOG(TS_OFF, VLEVEL_H, "\n\r"); } } APP_LOG(TS_OFF, VLEVEL_H, "\n\r"); /* Run PingPong process in background*/ UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0); /* USER CODE END OnRxDone */ } /* ??????*/ static void OnTxTimeout(void) { /* USER CODE BEGIN OnTxTimeout */ APP_LOG(TS_ON, VLEVEL_L, "OnTxTimeout\n\r"); /* Update the State of the FSM*/ State = S_TX_TIMEOUT; /* Run PingPong process in background*/ UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0); /* USER CODE END OnTxTimeout */ } /* ??????*/ static void OnRxTimeout(void) { /* USER CODE BEGIN OnRxTimeout */ APP_LOG(TS_ON, VLEVEL_L, "OnRxTimeout\n\r"); /* Update the State of the FSM*/ State = S_RX_TIMEOUT; /* Run PingPong process in background*/ UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0); /* USER CODE END OnRxTimeout */ } /* ??????*/ static void OnRxError(void) { /* USER CODE BEGIN OnRxError */ APP_LOG(TS_ON, VLEVEL_L, "OnRxError\n\r"); /* Update the State of the FSM*/ State = S_RX_ERROR; /* Run PingPong process in background*/ UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0); /* USER CODE END OnRxError */ } # define n 51.27 # define m -5.55 float change(int c) { float ph; ph=(c-n)/m; return ph; } int i=0; int k; void process_calibrated_data(void) { // ͳ¼ÆÖ÷ÒªÐÐΪ£¨±£Áô£© uint8_t counts[4] = {0}; for(int i=0; i<SAMPLES_TO_COLLECT; i++) { counts[prediction_results[i]]++; } uint8_t max_label = 0; for(int i=0; i<4; i++) { if(counts[i] > counts[max_label]) max_label = i; } printf("Dominant Behavior: %d\n", max_label); int16_t input_features[SAMPLES_TO_COLLECT][3]; /* ת»»ÎªKNNÊäÈë¸ñʽ */ for(int i=0; i<SAMPLES_TO_COLLECT; i++){ input_features[i][0] = calibrated_samples[i][0]; input_features[i][1] = calibrated_samples[i][1]; input_features[i][2] = calibrated_samples[i][2]; } /* Ö´ÐÐÔ¤²â²¢Í³¼Æ×¼È·¶È */ uint8_t correct_count = 0; for(int i=0; i<SAMPLES_TO_COLLECT; i++){ uint8_t pred = predict_class(input_features[i]); prediction_results[i] = pred; /* Óëʵ¼Ê±êÇ©±È½Ï£¨ÕâÀïÐèÒª¸ù¾Ýʵ¼ÊÇé¿öÐ޸ģ© */ if(pred == dataset[i].label) correct_count++; } /* Êä³ö½á¹û */ float accuracy = (float)correct_count/SAMPLES_TO_COLLECT*100; printf("Prediction Accuracy: %.1f%%\n", accuracy); } static uint8_t sample_count = 0; // ¶¨ÒåÒ»¸öÊý×éÀ´´æ´¢Ð£×¼ºóµÄÊý¾Ý #define SAMPLE_BUFFER_SIZE 10 static Vector1 sample_buffer[SAMPLE_BUFFER_SIZE]; static uint8_t buffer_index = 0; static void SendData_Process(void) { switch (State) { case S_IDLE: case S_TXing: break; case S_RX: Radio.Sleep(); State = S_IDLE; break; case S_TX: Radio.Sleep(); State = S_IDLE; break; case S_RX_TIMEOUT: case S_RX_ERROR: case S_TX_TIMEOUT: Radio.Sleep(); State = S_IDLE; break; case S_SEND_DATA: { MPU6050_Init(); int16_t AX, AY, AZ; for(int rain=0; rain<10; rain++) { MPU6050_GetData(&AX, &AY, &AZ); AX = AX/4 * 0.976; AY = AY/4 * 0.976; AZ = AZ/4 * 0.976; BufferTx[5+6*rain] = (AX < 0) ? 1 : 0; BufferTx[6+6*rain] = abs(AX)/100; BufferTx[7+6*rain] = (AY < 0) ? 1 : 0; BufferTx[8+6*rain] = abs(AY)/100; BufferTx[9+6*rain] = (AZ < 0) ? 1 : 0; BufferTx[10+6*rain] = abs(AZ)/100; printf("%d ",AX); printf("%d ",AY); printf("%d\n",AZ); /* ´«¸ÐÆ÷У׼ */ Vector1 raw_data = {AX, AY, AZ}; Vector1 calib_data = solve(raw_data); /* ´æ´¢µ½»º³åÇø */ if(buffer_index < SAMPLE_BUFFER_SIZE) { sample_buffer[buffer_index] = calib_data; buffer_index++; } printf("Sample %d: %.2f, %.2f, %.2f\n", buffer_index, calib_data.x, calib_data.y, calib_data.z); } /* µ±ÊÕ¼¯Âú10×éÊý¾Ýʱ½øÐÐÔ¤²â */ if(buffer_index >= SAMPLE_BUFFER_SIZE) { /* ת»»Êý¾Ý¸ñʽ¹©KNNʹÓà */ int16_t knn_input[SAMPLE_BUFFER_SIZE][3]; for(int i=0; i<SAMPLE_BUFFER_SIZE; i++) { knn_input[i][0] = (int16_t)(sample_buffer[i].x); knn_input[i][1] = (int16_t)(sample_buffer[i].y); knn_input[i][2] = (int16_t)(sample_buffer[i].z); } /* Ö´ÐÐÔ¤²â²¢Í³¼ÆÆ±Êý */ uint8_t votes[4] = {0}; // [0]:±êÇ©0µÄƱÊý£¬[1]:±êÇ©1... for(int i=0; i<SAMPLE_BUFFER_SIZE; i++) { uint8_t label = predict_class(knn_input[i]); BufferTx[75] = label; votes[label]++; } /* аæÍ¶Æ±Âß¼­ */ uint8_t final_label = 0; const uint8_t zero_votes = votes[0]; // ±êÇ©0µÄƱÊý // Ìõ¼þ1£º0µÄƱÊý¡Ý9ʱֱ½Ó·µ»Ø0 if(zero_votes >= 9) { final_label = 0; } // Ìõ¼þ2£ºÅųý0ºó±È½ÏÆäËû±êÇ© else { // ³õʼ»¯ÎªµÚÒ»¸ö·ÇÁã±êÇ© final_label = 1; uint8_t max_votes = votes[1]; // ±éÀú±êÇ©1-3ÕÒ×î´óÖµ for(uint8_t label=2; label<=3; label++){ if(votes[label] > max_votes){ final_label = label; max_votes = votes[label]; } // ƽƱʱѡÔñ±àºÅСµÄ±êÇ© else if(votes[label] == max_votes && label < final_label){ final_label = label; } } // ´¦ÀíÈ«ÁãµÄÌØÊâÇé¿ö£¨ÀíÂÛÉϲ»»á³öÏÖ£© if(max_votes == 0){ final_label = 0; // ½µ¼¶·µ»Ø0 } } printf("Final Prediction: %d\n", final_label); /* ÖØÖûº³åÇø */ buffer_index = 0; memset(sample_buffer, 0, sizeof(sample_buffer)); } /* ·¢ËÍԭʼÊý¾Ý£¨±£³ÖÔ­ÓÐÂß¼­£© */ BufferTx[0] = 5;//¶ÔÓ¦ÐòºÅ MX_SPI2_Init(); uint16_t ADCXX=0x00; uint8_t i=0; int ADCX=0; ADS1120reset(); HAL_Delay(20); ADCXX = ADS1120readonce(); if(ADCXX>32767) {ADCXX=3.15*(65534-ADCXX)/100; ADCX=ADCX-ADCXX; HAL_Delay(10); } if(ADCXX<32767) {ADCXX=3.15*ADCXX/100; ADCX=ADCX+ADCXX; HAL_Delay(10); } if(ADCXX==32767) { HAL_Delay(10); } ADCX=ADCX/50; printf("%d\r\n",ADCX); float a; a=change(ADCX); printf("%1.1f\r\n",a); SHT3x_Init(); float Temp,Hum; // if(ReadSHT3x(&Hum,&Temp)) // { if(Temp>=0) { printf("%.2f\n", Temp);// } else { printf("%.2f\n", Temp);// } } else {printf("error");} int zhengshu,xiaoshu; zhengshu=Temp*100/100; xiaoshu=Temp*100; xiaoshu=xiaoshu%100; BufferTx[1]=zhengshu; BufferTx[2]=xiaoshu; a=a*10; int b,c; b=(int)a/10; c=(int)a%10; c=c+1; BufferTx[3]=b; BufferTx[4]=c; Radio.Send(BufferTx, 80); State = S_TXing; break; } break; default: break; } } static void OnSendDataEvent(void *context) { // BSP_LED_On(LED_GREEN); // BSP_LED_On(LED_RED); UTIL_TIMER_Start(&timerSendData); if(State == S_IDLE) { State = S_SEND_DATA; UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0); } else { APP_PRINTF("OnSendDataEvent Error State(%d)\n\r",State); } } static char ReadSHT3x(float *Hum,float *Temp) { uint16_t HumData,TempData,HumCRC,TempCRC;//??????????? // SHT3x_WriteByte(0XE0,0X00); //????,????,????????? SHT3x_WriteByte(0X2C,0X0D); //????????(??????,Medium Repeatability) SHT3x_I2C_START(); //?????? SHT3x_I2C_SendByte(SHT3x_ADDRESS|0x01);//??????? WaitAck(); SHT3x_W_SCL(1); //??SCL?? while (!SHT3x_R_SCL()) ; //??????SCL?? TempData = SHT3x_ReadData(0); //?????8??? TempData=TempData<<8; //??8? // int c; // c=SHT3x_ReadData(0); TempData |= SHT3x_ReadData(0); //?????8??? TempCRC = SHT3x_ReadData(0); //????CRC???? HumData = SHT3x_ReadData(0); //?????8??? HumData=HumData<<8; //??8? HumData |= SHT3x_ReadData(0); //?????8??? HumCRC = SHT3x_ReadData(1); //????CRC???? SHT3x_I2C_STOP(); //?????? if( SHT3x_CRC_CAL(HumData)==HumCRC && SHT3x_CRC_CAL(TempData)==TempCRC ){ //????????CRC?? *Hum = (float)HumData*100/(65536-1); //????16?????????10?????? // *Temp=(-45+(175.0*((TempData<<8)+c)/65535.0))*100; // *Temp = (float)TempData*175/(65536-1)-45; //????16?????????10?????? return 1; } return 0; } static uint8_t SHT3x_CRC_CAL(uint16_t DAT) { uint8_t i,t,temp; uint8_t CRC_BYTE; CRC_BYTE = 0xFF; temp = (DAT>>8) & 0xFF; for(t = 0; t < 2; t++) { CRC_BYTE ^= temp; for(i = 0;i < 8;i ++) { if(CRC_BYTE & 0x80) { CRC_BYTE <<= 1; CRC_BYTE ^= 0x31; } else { CRC_BYTE <<= 1; } } if(t == 0) { temp = DAT & 0xFF; } } return CRC_BYTE; } 将knn改为支持向量机算法
07-14
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body with temperature-controlled fan ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "adc.h" #include "i2c.h" #include "icache.h" #include "spi.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "bsp_ili9341_4line.h" // Display library #include "string.h" // String manipulation #include "bsp_sht20.h" // SHT20 temperature/humidity sensor library /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ // System state enumeration for LED control typedef enum { STATE_LED1_ON, // LED1 is active STATE_LED3_ON // LED3 is active } SystemState; /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ // Pin definitions for buttons, LEDs, sensors and actuators #define KEY1_PIN GPIO_PIN_9 #define KEY1_PORT GPIOC #define KEY3_PIN GPIO_PIN_5 #define KEY3_PORT GPIOC #define IR_PIN GPIO_PIN_2 #define IR_PORT GPIOB #define MOTOR_PIN GPIO_PIN_7 #define MOTOR_PORT GPIOC #define LED1_PIN GPIO_PIN_4 #define LED1_PORT GPIOC #define LED3_PIN GPIO_PIN_13 #define LED3_PORT GPIOC #define FAN_PIN GPIO_PIN_6 // Added: Fan control pin #define FAN_PORT GPIOC // Added: Fan control port // Configuration parameters #define KEY_DEBOUNCE_DELAY 10 // Button debounce delay in ms #define PWM_PERIOD_US 10000// PWM period in microseconds #define TEMP_THRESHOLD 20.0 // Temperature threshold for fan (°C) /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ SystemState currentState = STATE_LED1_ON; // Current system state uint8_t key1_last = 1; // Previous state of KEY1 uint8_t key3_last = 1; // Previous state of KEY3 uint8_t pending_action = 0; // Flag for pending actions SHT20_TemRH_Val sht20_data; // Structure to store SHT20 data /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void SystemPower_Config(void); /* USER CODE BEGIN PFP */ void delay_us(uint32_t us); // Microsecond delay function void delay_ms(uint32_t ms); // Millisecond delay function void soft_pwm_led(GPIO_TypeDef* GPIOx, uint16_t pin, int duty); // Software PWM for LEDs /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /** * @brief Microsecond delay function * @param us: Number of microseconds to delay * @retval None */ void delay_us(uint32_t us) { volatile uint32_t n = us * 20; // Calibrated for STM32U5 at 160MHz while (n > 0) { n--; } } /** * @brief Millisecond delay function * @param ms: Number of milliseconds to delay * @retval None */ void delay_ms(uint32_t ms) { for (uint32_t i = 0; i < ms; i++) { delay_us(1000); // 1ms = 1000us } } /** * @brief Software PWM for LED brightness control * @param GPIOx: LED GPIO port * @param pin: LED pin number * @param duty: PWM duty cycle (0-100) * @retval None */ void soft_pwm_led(GPIO_TypeDef* GPIOx, uint16_t pin, int duty) { if (duty <= 0) { HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_RESET); return; } if (duty >= 100) { HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_SET); return; } // Calculate on/off times based on duty cycle uint32_t on_time = (duty * PWM_PERIOD_US) / 100; uint32_t off_time = PWM_PERIOD_US - on_time; // Apply PWM signal HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_SET); delay_us(on_time); HAL_GPIO_WritePin(GPIOx, pin, GPIO_PIN_RESET); delay_us(off_time); } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* 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(); /* Configure the System Power */ SystemPower_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_ICACHE_Init(); MX_SPI1_Init(); MX_ADC4_Init(); MX_I2C1_Init(); /* USER CODE BEGIN 2 */ // Initialize display ILI9341_Init(); // Initialize ILI9341 display ILI9341_Clear(RED); // Clear screen with red (initialization indicator) delay_ms(500); // Show red for 500ms ILI9341_Clear(WHITE); // Clear screen to white for normal operation // Calibrate ADC4 HAL_PWREx_EnableVddA(); HAL_PWREx_EnableVddIO2(); if(HAL_ADCEx_Calibration_Start(&hadc4,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED)!= HAL_OK) { Error_Handler(); } // Initialize fan pin as output HAL_GPIO_WritePin(FAN_PORT, FAN_PIN, GPIO_PIN_RESET); // Start with fan off /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { uint8_t str[5][30]; // Increased array size for fan status uint32_t buf[2] = {0}; int i; // 1. Read SHT20 temperature and humidity data sht20_data = BSP_SHT20_GetData_Queue(); // 2. Read internal ADC temperature HAL_ADC_Start(&hadc4); for(i = 0; i < 2; i++) { HAL_ADC_PollForConversion(&hadc4,100); buf[i] = HAL_ADC_GetValue(&hadc4); } HAL_ADC_Stop(&hadc4); float internal_temp = (((buf[0]*3.3/4095)*1000)-685)/2.5; // 3. Control fan based on external temperature if (sht20_data.Tem > TEMP_THRESHOLD) { HAL_GPIO_WritePin(FAN_PORT, FAN_PIN, GPIO_PIN_SET); // Turn fan on sprintf((char*)str[4], "Fan: ON (Temp > 20C)"); } else { HAL_GPIO_WritePin(FAN_PORT, FAN_PIN, GPIO_PIN_RESET); // Turn fan off sprintf((char*)str[4], "Fan: OFF (Temp <= 20C)"); } // 4. Determine current LED state for display if (currentState == STATE_LED1_ON) { sprintf((char*)str[3], "Current LED: LED1 ON"); } else if (currentState == STATE_LED3_ON) { sprintf((char*)str[3], "Current LED: LED3 ON"); } else { sprintf((char*)str[3], "Current LED: Unknown"); } // 5. Display information on screen (5 lines total) ILI9341_Clear(WHITE); // Clear screen to white // Line 1: SHT20 external temperature (y=30) sprintf((char*)str[0], "Ext Temp:%.2fC", sht20_data.Tem); Gui_DrawFont_GBK16(10, 30, BLACK, WHITE, str[0]); // Line 2: SHT20 external humidity (y=60) sprintf((char*)str[1], "Ext Hum :%.2f%%RH", sht20_data.Hum); Gui_DrawFont_GBK16(10, 60, BLACK, WHITE, str[1]); // Line 3: Internal temperature (y=90) sprintf((char*)str[2], "Int Temp:%.2fC", internal_temp); Gui_DrawFont_GBK16(10, 90, BLACK, WHITE, str[2]); // Line 4: Current LED state (y=120) Gui_DrawFont_GBK16(10, 120, BLACK, WHITE, str[3]); // Line 5: Fan status (y=150) - new line for fan information Gui_DrawFont_GBK16(10, 150, BLACK, WHITE, str[4]); // 6. Button, IR sensor, LED and motor logic uint8_t key1_curr = HAL_GPIO_ReadPin(KEY1_PORT, KEY1_PIN); uint8_t key3_curr = HAL_GPIO_ReadPin(KEY3_PORT, KEY3_PIN); uint8_t ir_blocked = HAL_GPIO_ReadPin(IR_PORT, IR_PIN); // IR sensor status indicator HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, ir_blocked ? GPIO_PIN_SET : GPIO_PIN_RESET); // Button debounce handling if (key1_last == 1 && key1_curr == 0) { delay_ms(KEY_DEBOUNCE_DELAY); if (HAL_GPIO_ReadPin(KEY1_PORT, KEY1_PIN) == 0) { pending_action = 1; } } if (key3_last == 1 && key3_curr == 0) { delay_ms(KEY_DEBOUNCE_DELAY); if (HAL_GPIO_ReadPin(KEY3_PORT, KEY3_PIN) == 0) { pending_action = 2; } } // Update button states key1_last = key1_curr; key3_last = key3_curr; // LED state machine and motor control if (currentState == STATE_LED1_ON) { soft_pwm_led(LED1_PORT, LED1_PIN, 100); soft_pwm_led(LED3_PORT, LED3_PIN, 0); if (pending_action == 2 && !ir_blocked) { pending_action = 0; HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_PIN, GPIO_PIN_SET); // Smooth transition between LEDs for (int level = 100; level >= 0; level--) { soft_pwm_led(LED1_PORT, LED1_PIN, level); soft_pwm_led(LED3_PORT, LED3_PIN, 100 - level); delay_ms(10); } HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_PIN, GPIO_PIN_RESET); currentState = STATE_LED3_ON; } } else if (currentState == STATE_LED3_ON) { soft_pwm_led(LED1_PORT, LED1_PIN, 0); soft_pwm_led(LED3_PORT, LED3_PIN, 100); if (pending_action == 1 && !ir_blocked) { pending_action = 0; HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_PIN, GPIO_PIN_SET); // Smooth transition between LEDs for (int level = 100; level >= 0; level--) { soft_pwm_led(LED3_PORT, LED3_PIN, level); soft_pwm_led(LED1_PORT, LED1_PIN, 100 - level); delay_ms(10); } HAL_GPIO_WritePin(MOTOR_PORT, MOTOR_PIN, GPIO_PIN_RESET); currentState = STATE_LED1_ON; } } HAL_Delay(1000); // Update every 1 second /* 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 */ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.MSIState = RCC_MSI_ON; RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4; RCC_OscInitStruct.PLL.PLLM = 3; RCC_OscInitStruct.PLL.PLLN = 10; RCC_OscInitStruct.PLL.PLLP = 2; RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLR = 1; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; RCC_OscInitStruct.PLL.PLLFRACN = 0; 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_CLOCKTYPE_PCLK2 |RCC_CLOCKTYPE_PCLK3; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { Error_Handler(); } } /** * @brief Power Configuration * @retval None */ static void SystemPower_Config(void) { /* * Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral */ HAL_PWREx_DisableUCPDDeadBattery(); /* USER CODE BEGIN PWR */ /* USER CODE END PWR */ } /* USER CODE BEGIN 4 */ /* 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 */ __disable_irq(); // Blink LED to indicate error while(1) { HAL_GPIO_TogglePin(LED1_PORT, LED1_PIN); delay_ms(500); } /* 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 */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ 代码不动 把英文注释换成中文
最新发布
10-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值