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() 中用到。

#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
/* Edge Impulse Arduino examples * Copyright (c) 2022 EdgeImpulse Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // These sketches are tested with 2.0.4 ESP32 Arduino Core // https://github.com/espressif/arduino-esp32/releases/tag/2.0.4 // If your target is limited in memory remove this macro to save 10K RAM #define EIDSP_QUANTIZE_FILTERBANK 0 /* ** NOTE: If you run into TFLite arena allocation issue. ** ** This may be due to may dynamic memory fragmentation. ** Try defining "-DEI_CLASSIFIER_ALLOCATION_STATIC" in boards.local.txt (create ** if it doesn't exist) and copy this file to ** `<ARDUINO_CORE_INSTALL_PATH>/arduino/hardware/<mbed_core>/<core_version>/`. ** ** See ** (https://support.arduino.cc/hc/en-us/articles/360012076960-Where-are-the-installed-cores-located-) ** to find where Arduino installs cores on your machine. ** ** If the problem persists then there's not enough memory for this model and application. */ /* Includes ---------------------------------------------------------------- */ #include <Project-name_inferencing.h> #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" /** Audio buffers, pointers and selectors */ typedef struct { int16_t *buffer; uint8_t buf_ready; uint32_t buf_count; uint32_t n_samples; } inference_t; static inference_t inference; static signed short sampleBuffer[EI_CLASSIFIER_RAW_SAMPLE_COUNT]; static bool debug_nn = false; // Set this to true to see e.g. features generated from the raw signal static bool record_status = true; static TaskHandle_t xCaptureTaskHandle = NULL; const int led = 21; const int led_record = 8; const int AUDIO_IN = 0; // 选择 GPIO 0 作为模拟输入 /** * @brief Arduino setup function */ void setup() { // put your setup code here, to run once: Serial.begin(115200); // comment out the below line to cancel the wait for USB connection (needed for native USB) while (!Serial) ; Serial.println("Edge Impulse Inferencing"); // summary of inferencing settings (from model_metadata.h) ei_printf("Inferencing settings:\n"); ei_printf("\tInterval: "); ei_printf_float((float)EI_CLASSIFIER_INTERVAL_MS); ei_printf(" ms.\n"); ei_printf("\tFrame size: %d\n", EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE); ei_printf("\tSample length: %d ms.\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT / 16); ei_printf("\tNo. of classes: %d\n", sizeof(ei_classifier_inferencing_categories) / sizeof(ei_classifier_inferencing_categories[0])); ei_printf("\nStarting continious inference in 2 seconds...\n"); pinMode(led, OUTPUT); pinMode(led_record, OUTPUT); digitalWrite(led, 1); ei_sleep(2000); digitalWrite(led, 0); if (microphone_inference_start(EI_CLASSIFIER_RAW_SAMPLE_COUNT) == false) { ei_printf("ERR: Could not allocate audio buffer (size %d), this could be due to the window length of your model\r\n", EI_CLASSIFIER_RAW_SAMPLE_COUNT); return; } ei_printf("Recording...\n"); xTaskNotifyGive(xCaptureTaskHandle); } /** * @brief Arduino main function. Runs the inferencing loop. */ float max_probability = 0; int max_probability_ix = 0; void loop() { bool m = microphone_inference_record(); if (!m) { ei_printf("ERR: Failed to record audio...\n"); return; } signal_t signal; signal.total_length = EI_CLASSIFIER_RAW_SAMPLE_COUNT; signal.get_data = &microphone_audio_signal_get_data; ei_impulse_result_t result = {0}; EI_IMPULSE_ERROR r = run_classifier(&signal, &result, debug_nn); if (r != EI_IMPULSE_OK) { ei_printf("ERR: Failed to run classifier (%d)\n", r); return; } // print the predictions ei_printf("Predictions "); ei_printf("(DSP: %d ms., Classification: %d ms., Anomaly: %d ms.)", result.timing.dsp, result.timing.classification, result.timing.anomaly); ei_printf(": \n"); max_probability = 0; max_probability_ix = 0; for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) { ei_printf(" %s: ", result.classification[ix].label); ei_printf_float(result.classification[ix].value); ei_printf("\n"); if (max_probability <= result.classification[ix].value) { max_probability = result.classification[ix].value; max_probability_ix = ix; } } if (strcmp(result.classification[max_probability_ix].label, "beihang") == 0) { ei_printf("北京航空航天大学\n"); digitalWrite(led, LOW); } else if (strcmp(result.classification[max_probability_ix].label, "shie") == 0) { ei_printf("士谔书院\n"); digitalWrite(led, HIGH); } else if (strcmp(result.classification[max_probability_ix].label, "hyn") == 0) { ei_printf("何玥凝\n"); digitalWrite(led, 0); } else if (strcmp(result.classification[max_probability_ix].label, "hsy") == 0) { ei_printf("黄诗莹\n"); digitalWrite(led, 0); } else { ei_printf("未检测到有效指令\n"); digitalWrite(led, LOW); } #if EI_CLASSIFIER_HAS_ANOMALY == 1 ei_printf(" anomaly score: "); ei_printf_float(result.anomaly); ei_printf("\n"); #endif xTaskNotifyGive(xCaptureTaskHandle); } static void audio_inference_callback(uint32_t n_bytes) { ei_printf("DATA "); for (int i = 0; i < n_bytes; i++) { inference.buffer[inference.buf_count++] = sampleBuffer[i]; if (inference.buf_count >= inference.n_samples) { inference.buf_count = 0; inference.buf_ready = 1; } // if(i > 8000 ) { ei_printf("%d ", sampleBuffer[i]); } } ei_printf("\n"); } unsigned long pre_time = 0; const byte sample_interval = 125; //采样时间间隔125us,即采样率8kHz const byte scale = 4; //幅度缩放因子 const int thresh = 400; int adcValue = 0; bool ADCfast(void) { static int zero = 580; int curSample = 0; static unsigned long prevTime; long val = 0; bool Collecting = false; unsigned long triggerTimeout = millis(); // 超时计时 while(!Collecting && (millis() - triggerTimeout < 2000)){ prevTime = micros(); adcValue = analogRead(AUDIO_IN); // 读取模拟信号 val = adcValue / scale; // 将ADC采样值进行尺度缩放 // 去除直流偏置值 if (val < zero) zero--; else zero++; val = val - zero; if (abs(val) > thresh){ Collecting = true; break; } while (micros() - prevTime < sample_interval); } for (curSample = 0; curSample < EI_CLASSIFIER_RAW_SAMPLE_COUNT; curSample++) { prevTime = micros(); adcValue = analogRead(AUDIO_IN); // 读取模拟信号 val = adcValue / scale; // 将ADC采样值进行尺度缩放 // 去除直流偏置值 if (val < zero) zero--; else zero++; val = val - zero; sampleBuffer[curSample] = val; while (micros() - prevTime < sample_interval); } return Collecting; } static void capture_samples(void *arg) { const int32_t bytes_to_read = (uint32_t)arg; size_t bytes_read = bytes_to_read; const int32_t threshold = 625; int threshold_cnt; int start_point; while (record_status) { ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(5000)); ei_printf("----------------请说语音指令----------------\n"); digitalWrite(led_record, LOW); ADCfast(); digitalWrite(led_record, HIGH); if (record_status) { audio_inference_callback(EI_CLASSIFIER_RAW_SAMPLE_COUNT); } else { break; } vTaskDelay(pdMS_TO_TICKS(2000)); } vTaskDelete(NULL); } /** * @brief Init inferencing struct and setup/start PDM * @param [in] n_samples The n samples * @return { description_of_the_return_value } */ static bool microphone_inference_start(uint32_t n_samples) { inference.buffer = (int16_t *)malloc(n_samples * sizeof(int16_t)); if (inference.buffer == NULL) { return false; } inference.buf_count = 0; inference.n_samples = n_samples; inference.buf_ready = 0; ei_sleep(100); record_status = true; xTaskCreate(capture_samples, "CaptureSamples", 1024 * 32, (void *)(EI_CLASSIFIER_RAW_SAMPLE_COUNT * sizeof(sampleBuffer[0])), 10, &xCaptureTaskHandle); return true; } static bool microphone_inference_record(void) { bool ret = true; while (inference.buf_ready == 0) { delay(10); } inference.buf_ready = 0; return ret; } static int microphone_audio_signal_get_data(size_t offset, size_t length, float *out_ptr) { numpy::int16_to_float(&inference.buffer[offset], out_ptr, length); return 0; } static void microphone_inference_end(void) { ei_free(inference.buffer); } #if !defined(EI_CLASSIFIER_SENSOR) || EI_CLASSIFIER_SENSOR != EI_CLASSIFIER_SENSOR_MICROPHONE #error "Invalid model for current sensor." #endif 这个代码,我需要通过麦克风读入外界音频进行识别,但是实际上对于大多是人声,这个代码在串口监视器里面反馈的都是label何玥凝,其他标签反馈不出来,现在已知是模型精确度很高,达到97%
05-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值