合宙Air105 单片机学习
内容纲要

合宙Air 105 学习

  • C语言开发 使用Keil 编写代码

    GPIO 引脚 
    
  • GPIO 端口的重映射

    // 疑惑点, 关于GPIO_Remap_0 这个问题,如果不是看原理图或者 Demo的宏定义命名,根本不知道它映射的什么端口
    void GPIO_PinRemapConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_RemapTypeDef GPIO_Remap){} // 端口映射 map 映射对象为GPIO_Remap_0、1、2、3
    
    // 目前案例中,要求是把GPIO 映射成 Uart  
    

    image-20230625120202959

1

  • IER 中断使能寄存器

    // 下方截取代码部分片段,中断
      if (DISABLE != UART_FIFOInitStruct->FIFO_TX_TriggerIntEnable)
      {
          UARTx->OFFSET_4.IER |= UART_IER_PTIME;    
      }
      else
      {
          UARTx->OFFSET_4.IER &= ~UART_IER_PTIME;    
      }
    
  • 使用 Jlink 仿真器 报错 Error: Flash* Download failed - "Cortex-M4"

    # 解决经验 
    目前遇到的这个问题点在于Target 的ROM 和RAM 地址问题
    导致Jlink设备不识别Cortex 的CPU , 因此按照官方的工程设置Target 的地址
    

    image-20230625171016230

TODO:// 读GPIO 串口 SPI

TODO://

  1. 按键输入, GPIO 按键输入
  2. UART 串口
  3. SPI
  4. I2C
  5. GPIO 模拟串口,实现半双工通信

GPIO 按键输入

  • Air105 没看到GPIO 的中断向量函数

    // Air 105 芯片对GPIO 端口的电平操作是通过置位/复位进行操作 (而非端口寄存器)。
    void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    
    // 我感觉 Air105 的库没有 GPIO 的中断服务函数。
    /*
    在使用Air105 C库开发的时候,没有GPIO 的中断,导致要监听一个按键时,需要用一个循环不断扫描它。
    
    */
    
  • GPIO 输入函数

    // 监听GPIO A...F 的pin 输入的数
    uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); 
    
    // 监听GPIO A...F 到底是哪一个pin 在输入
    uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);
    
  • 使用端口重映射,映射口应该可以自定义(但多个外设不能重复)。

    GpioA_10.GPIO_Pin = GPIO_Pin_10; 
    GpioA_10.GPIO_Mode = GPIO_Mode_IPU;  // GPIO 输入
      GpioA_10.GPIO_Remap = GPIO_Remap_3;  // GPIO 重新映射'
    
    GPIO_PinRemapConfig(GPIOC, GPIO_Pin_1, GPIO_Remap_1);  // 根据端口引脚来映射成uart 端口
  • 主要踩坑的地方

    1. SPI 映射的引脚问题
    
    2. HSPI 高速SPI 映射的引脚可不是中间的SPIM0 ,而是旁边的排针。。。
    
    3. GPIO_InitStruct.GPIO_Remap = GPIO_Remap_CS; 哪怕前面 Reamap 把这个引脚重映射了之后,这个函数也不能少,emmm 因为我前面结构体没用官方函数初始化
    
    4. SPI 必须发送数据的时候时钟引脚才会有电压周期变化。(这一点很坑)我以为时钟会一直变化,结果不发数据他就不动。。。
    

UART 说明

  • 在使用uart 串口中断时,遇到按照常理配置了但串口不发送东西的问题

    TIP: 别看这里这么简单排错,但是没有文档的时候又有BUG( 你根本找不到错误点 ),会把你恶心坏的

    // 最后找出原因,GPIO 重映射的问题, 一个串口对应一个GPIO_Remap_   ,该问题点官方文档并未说明,且未说明Remap 应该映射的引脚。 最后还是自己试出来的。
    GPIO_PinRemapConfig(GPIOD, GPIO_Pin_12, GPIO_Remap_0);  // GPIO 引脚的映射
    
    这里给个引脚映射说明
      GPIO_Remap_3 ----> Uart1  PC1--tx   PC0---rx
      GPIO_Remap_0 ----> Uart2  PD13--tx  PD12---rx
      GPIO_Remap_2 ----> Uart3  PE9--tx   PE8--rx
      //默认 GPIO_Remap_0 ----> Uart0  PA1    PA0
    
  • 串口发送字符串的方法( 在合宙Air105 中,发送字符串被封装成FIFO 相关的结构体配置 )

    在stm32F4系列中,可以判断寄存器标志位,但在air105 将其封装为

    UART_FIFOInitTypeDef UART_FIFOInitStruct;
    
    UART_FIFOInitStruct.FIFO_Enable = ENABLE;
      UART_FIFOInitStruct.FIFO_DMA_Mode = UART_FIFO_DMA_Mode_1;
      UART_FIFOInitStruct.FIFO_RX_Trigger = UART_FIFO_RX_Trigger_1_4_Full;
      UART_FIFOInitStruct.FIFO_TX_Trigger = UART_FIFO_TX_Trigger_2_Chars;
      UART_FIFOInitStruct.FIFO_TX_TriggerIntEnable = ENABLE;
    
  • ring_buffer 环形队列缓冲区 github参考代码仓库 参考示例理论文档

    // 作用:用于接收串口发送过来的长字符串,
    

SPI 使用

  • void SPI_Init(SPI_TypeDef SPIx, SPI_InitTypeDef SPI_InitStruct); 函数

    void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
    
  • HSPI 高速SPI 映射口

SPI0_CSN PB13
SPI0_CL PB12
SPI0_MI PB15
SPI0_MO PB14
  • SPI2 映射

    
    // HSPI0 
    judge_GPIO_REMAP(2,1);  // 高速spi0 专用  SPI引脚映射为 GPIO_Remap_2, CS片选引脚映射为1
    
    // 这是普通的 SPI0
    GPIO_PinRemapConfig(GPIOB, GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15, GPIO_Remap_0); 
    
    //SPI1
    
    // SPI2 可用
    GPIO_PinRemapConfig(GPIOB, GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5, GPIO_Remap_0);
    
    iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 8052 -j DNAT --to 172.16.2.11:4
    

中断遇到的问题

下方是中断遇到的2个不同的函数,解释说明

// 这两个函数都一样,只不过一个是ST 公司做的,一个是ARM 公司做的。(但在air105 中得使用ST 公司的,也就是core_cm4.h 中的函数 )

  NVIC_SetPriorityGrouping(NVIC_PriorityGroup_0);  // 这个时core_cm4.h 中的函数  设置中断优先级分组方式
   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);  // 这个misc.c 中的函数  设置中断优先级分组

中断服务函数被不断循环

// 1.如果按住PC3 按键再上电,设备就不会进入中断服务函数, 如果松开,他就一直打印中断服务函数的东西。
// 2.如果直接上电,它就直接打印

排查原因:
    中断没到来的时候不打印输出,但是中断一到就一直循环输出,说明这次中断标志位没有重置,导致系统以为下次中断也到了。因此要在中断服务函数中添加如下的清除函数。
EXTI_ClearITPendingBit(EXTI_Line0);

关于固件烧写的一个案例

  • 固件烧写入Flash 因为时钟或者别的代码部分可能更改了PC3 的设置(SW 烧录引脚),导致后续使用Jlink 识别不了芯片。( 解决办法:使用合宙usb 刷入一个初始化soc 再使用Keil 烧录固件 )

    找到原因: 因为我使用过SYSCTRL_APBPeriphResetCmd(SYSCTRL_APBPeriph_ALL, ENABLE); // 外设时钟复位 导致仿真器识别不了要烧写的芯片。可能是把时钟给复位了

ThreadX

  • 对于threadx 是应用层的框架,移植到stm 单片机上,他不会对底层有影响,

    而是需要修改的部分是:
    1.Vector向量表的修改。
    2.告诉上层ThreadX 中断需要执行什么函数。

    因此:

      Threadx 并不关心stm32 单片机底层寄存器之类的地址问题。ThreadX 可以理解成一个死循环,在死循环中会有一种机制,将各类的循环分割开来,并设有优先级。如果你要使用底层GPIO 或者别的外设,还是像以前一样操作库函数 或者直接操作GPIO。

  • threadX 移植中遇到的困难:

    1. 系统中断函数的设置问题。
    2. 汇编语言报错????而且是注释部分 /**/ 也报错( 可是这是微软官方给的汇编配置文件啊 )
  • 使用AC6 编译,就不会出现那么多报错。但是可能Air105 的固件库不支持AC6 编译

    ../../Libraries/CMSIS/Include\core_cm4.h(94): note: expanded from macro '__ASM'
    
    ../../Libraries/Air105_StdPeriph_Driver/src/air105_sysctrl.c(175): error: expected identifier or '('
    __STATIC_INLINE __ASM void SYSCTRL_Sleep(void)
    
  • 回到keil 目录下的AC5 编译报错: 是 tx_thread_schedule.s 提示寄存器超过最大数量限制。

    
    Keil 编译器报错 LDM/STM instruction exceeds maximum register count 5 allowed with --split_ldm

    解决办法:

      根据chatGPT 提供的思路,修改汇编语言,( 我是不懂汇编的,可能只单纯能猜出汇编中部分代码是干什么的 ),

    ; 报错点1
    ;STMDB   r12!, {r4-r11}                          ; Save its remaining registers 原始代码
    STMDB   r12!, {r4-r7} 
    STMDB   r12!, {r8-r11} 
    
    ; 报错点2
    ;LDMIA   r12!, {r4-r11}                          ; Recover thread's registers 原始代码
    
    LDMIA   r12!, {r4-r7}                          ; Restore r4-r7
    LDMIA   r12!, {r8-r11}                         ; Restore r8-r11
    
    在ThreadX的tx_thread_schedule.s文件中,STMDB r12!, {r4-r11}是对寄存器的保存操作,而不是声明或初始化操作。
    
    该指令用于将寄存器r4到r11的值保存到内存中,同时递减栈指针r12的值,以便为将来的恢复操作留出空间。STMDB是"Store Multiple Decrement Before"的缩写,表示先递减栈指针,再存储多个寄存器的值。
    
    在ThreadX的上下文切换中,寄存器的保存和恢复是为了保存和恢复线程的上下文信息,以确保线程切换后能够正确恢复执行。在调度器切换到下一个线程之前,当前线程的寄存器状态被保存到其线程控制块(TCB)中,以便下次切换回该线程时能够正确恢复执行。
    
    请注意,具体的寄存器使用和保存方式可能因处理器架构和ThreadX的移植实现而有所不同,以上解释是一般情况下的典型用法。对于特定的移植和平台,请参考相关的移植文档或具体的代码实现。

解决办法:

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇