AD7606搭配F103ZET6HAL库使用笔记记录,精总

首先要确定好各个晶振频率,因为有的过程有时序长短需求,不同的频率,执行的每句代码的时间都不同,使用HAL库和使用标准库的速度也有差别。

一.硬件接口介绍

汇总:

1.OS[0-2]过采样率设置

2.6号PAS/SER,接1串口输出,接0并口输出(这里直接接3.3V)

3.7号STBY(这里直接接3.3V,到什么手持设备考虑节约用电时再考虑)

4.8号RANGE,=1(+-10v量程)    =0(+-5v量程),(单片机控制)

5.9,10号CONVST A, CONVST B     用于启动ADC通道采样, 这里将这两个一起短接(1个负责4个ADC通道),上升沿后开始转化,所以常态为1,要开始转化的时候,拉低后,在拉高,引出上升沿

6.RESET,上升沿复位,所以默认是0,要复位拉1.

7.12.  RD/SCLK    SPI_SCK   时钟线

8.13.CS片选   低电平有效,对于串行传输,(默认高电平)给低电平时,开始读取data

如图

9.14脚BUSY,CONVST A和B同时到达上升沿后,BUSY拉高表示开始转换,拉低后,表示转换完成,可以开始拉低cs来读data

如图

10.15脚FRSTDATA可以先不管

11.22 to 16 DB[6:0]并行输出,先不管我们用串行

12.24脚 DB7/DOUTA  串行data输出口,这里用成SPI_MISO

13.DB8/DOUTB,不管

其余DB接口都想不管接地

14.34脚REF SELECT:1内部电压基准源使用  0外部使用

15.42脚 REFIN/ REFOUT,if ࡕREF SELECT=1,则输出2.5v基准源给外部,

else ifࡕREF SELECT=0,则作为基准源输入

二.代码流程思路;

1.初始化:

    /* 设置过采样模式 */
     Ad7606_SetOS(5);//32倍过采样

    /* 设置采集量程模式 */

   AD_RANGE_5V_HAL();    

 /* 硬件复位复AD7606 */
    Ad7606_Reset();  

2.开始转化工作

此阶段参考思路图

 /* CONVST脚设置为高电平   CONVSTAB同时进入高电平 方便一起拉低 来下一步进行AD转换*/   

    AD_CONVST_HIGH();             

注意:

/* 上升沿开始转换,低电平持续时间至少25ns   1/25ns=40Mhz
  上升沿开始转换,低电平持续时间至少25ns, 1/25ns=40Mhz,延时的确定和单片机的主频有关 */
    //直接操作寄存器   提升10倍速度     

 //拉低CONVSTA或者CONVSTB持续最多0.5ms(500ns),注意这里是最多,所以在代码里只需一个参考时钟周期足以,比如你用的100M,一个参考时钟周期就是10ns,当然,CONVSTA和CONVSTB也可同时拉低,这样就是8个通道同时采集
    /* CONVST脚设置为高电平   CONVST同时进入高电平 上升沿时开始转换*/    

    AD_CONVST_LOW_HAL();    

/* 连续执行1次,低电平约200ns */(硬件上CONVEST A和B接一起了)

外部BUSY开始拉高(我们要读下降沿,也是低电平,来确认转换完成)

    /* BUSY = 0 时.ad7606处于空闲状态ad转换结束 */    
    if (HAL_GPIO_ReadPin(AD_BUSY_GPIO_PORT, AD_BUSY_PIN)== 0)        

3.开始接受data

//准备开始读取拉低CS失能AD_7606  停止转换

        AD_CS_LOW_HAL();

        for (i = 0; i < CH_NUM; i++)
        {
              pusData[i] =Ad7606_MN_ReadBytes();    
            //串行输出模式下只有两个数字输出通道,每个输入通道输出16位采样数据;
            //AD一共有8个通道,从时序上说,每返回一次,下一次spi返回下一个通道的值
            //所以此处使用for  8次循环  获取8次通道值8*16bit位
            //所以此处 pusData[0-7]正是 AD7606的八个通道值
            //所以此处使用for  8次循环  获取8次通道值
        }        

其中Ad7606_MN_ReadBytes函数

在SCLK的上升沿AD7606输出一位数据(但根据时序图,我感觉是SCLK高电平期间输出的)当一个通道一次转换后输出16位采样数据;

for (i = 0; i < 16; i++)//18次循环
    {
        SCLK_LOW_HAL();
        uiData = uiData << 1;
        uiData |= DATA_HAL();
        SCLK_HIGH_HAL();
    }
  usData =uiData;

对于AD7608这里16变成18就可以了

4.接收data后开始数据转换

具体原理参考python将AD7606B原始补码数据数组转换原码数据数组并进行处理_ad7606补码转换计算-CSDN博客

         AD_V[0]=5000*AD_Value[0]/32768;
          if(AD_V[0]>5000)
          {
              AD_V[0]=-(10000-AD_V[0]);
          }

          AD_V[1]=5000*AD_Value[1]/32768;
          if(AD_V[1]>5000)
          {
              AD_V[1]=-(10000-AD_V[1]);
          }
          
          AD_V[2]=5000*AD_Value[2]/32768;
          if(AD_V[2]>5000)
          {
              AD_V[2]=-(10000-AD_V[2]);
          }
          
          AD_V[3]=5000*AD_Value[3]/32768;
          if(AD_V[3]>5000)
          {
              AD_V[3]=-(10000-AD_V[3]);
          }

到此读取完成,有朋友需要单片机搭配CUBEMX,全源代码工程的私聊我,自己手搓实属不易。

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里给出一个简单的基于HAL库的STM32F103ZET6 bootloader代码示例: ```c #include "main.h" #define BOOTLOADER_VERSION "1.0" #define BOOTLOADER_ADDR 0x08000000 // Bootloader程序存储地址 #define APPLICATION_ADDR 0x08004000 // 应用程序存储地址 #define FLASH_PAGE_SIZE 2048 // flash每页大小 #define APP_MAGIC_CODE 0x5A5A // 应用程序标志码 // 函数声明 void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); static void MX_CRC_Init(void); static void JumpToApp(void); void FlashErase(uint32_t addr); void FlashWrite(uint32_t addr, uint8_t *data, uint32_t size); uint16_t CRC16(uint8_t *data, uint32_t size); // 全局变量 CRC_HandleTypeDef hcrc; UART_HandleTypeDef huart1; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); MX_CRC_Init(); uint8_t buffer[256]; uint32_t size, addr, crc; uint16_t magic_code; // 检查是否需要进入bootloader模式 if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_RESET) { // 进入bootloader模式 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET); // 发送欢迎信息 HAL_UART_Transmit(&huart1, (uint8_t *)"--------------------------------------\r\n", 44, HAL_MAX_DELAY); HAL_UART_Transmit(&huart1, (uint8_t *)"STM32F103ZET6 Bootloader\r\n", 29, HAL_MAX_DELAY); HAL_UART_Transmit(&huart1, (uint8_t *)"Version: ", 9, HAL_MAX_DELAY); HAL_UART_Transmit(&huart1, (uint8_t *)BOOTLOADER_VERSION, strlen(BOOTLOADER_VERSION), HAL_MAX_DELAY); HAL_UART_Transmit(&huart1, (uint8_t *)"\r\n", 2, HAL_MAX_DELAY); // 等待数据传输 while (1) { // 接收地址 HAL_UART_Receive(&huart1, (uint8_t *)&addr, 4, HAL_MAX_DELAY); // 接收大小 HAL_UART_Receive(&huart1, (uint8_t *)&size, 4, HAL_MAX_DELAY); // 接收校验码 HAL_UART_Receive(&huart1, (uint8_t *)&crc, 4, HAL_MAX_DELAY); // 接收数据 HAL_UART_Receive(&huart1, buffer, size, HAL_MAX_DELAY); // 计算数据校验码 if (CRC16(buffer, size) != crc) { // 发送错误信息 HAL_UART_Transmit(&huart1, (uint8_t *)"CRC error!\r\n", 12, HAL_MAX_DELAY); } else { // 写入flash FlashErase(addr); FlashWrite(addr, buffer, size); // 发送成功信息 HAL_UART_Transmit(&huart1, (uint8_t *)"Write success!\r\n", 16, HAL_MAX_DELAY); } // 接收标志码 HAL_UART_Receive(&huart1, (uint8_t *)&magic_code, 2, HAL_MAX_DELAY); // 检查标志码是否正确 if (magic_code == APP_MAGIC_CODE) { // 跳转到应用程序 JumpToApp(); } } } else { // 检查应用程序标志码 magic_code = *((uint16_t *)APPLICATION_ADDR); if (magic_code == APP_MAGIC_CODE) { // 跳转到应用程序 JumpToApp(); } } while (1) { } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; /**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /**Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_AFIO_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); /*Configure GPIO pin : PC13 */ GPIO_InitStruct.Pin = GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); } static void MX_CRC_Init(void) { hcrc.Instance = CRC; hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE; hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE; hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE; hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE; hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; if (HAL_CRC_Init(&hcrc) != HAL_OK) { Error_Handler(); } } static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } void JumpToApp(void) { // 关闭中断 __disable_irq(); // 跳转到应用程序 uint32_t jump_address = *((volatile uint32_t *)(APPLICATION_ADDR + 4)); void (*application)(void) = (void (*)(void))jump_address; application(); } void FlashErase(uint32_t addr) { // 解锁flash HAL_FLASH_Unlock(); // 擦除flash FLASH_EraseInitTypeDef erase = { .TypeErase = FLASH_TYPEERASE_PAGES, .Banks = FLASH_BANK_1, .PageAddress = addr, .NbPages = 1}; uint32_t error; HAL_FLASHEx_Erase(&erase, &error); // 上锁flash HAL_FLASH_Lock(); } void FlashWrite(uint32_t addr, uint8_t *data, uint32_t size) { uint32_t i; // 解锁flash HAL_FLASH_Unlock(); // 写入flash for (i = 0; i < size; i += 2) { uint16_t value = (uint16_t)data[i] | ((uint16_t)data[i + 1] << 8); HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr + i, value); } // 上锁flash HAL_FLASH_Lock(); } uint16_t CRC16(uint8_t *data, uint32_t size) { uint32_t crc = 0xFFFFFFFF; for (uint32_t i = 0; i < size; i++) { crc ^= (uint32_t)(data[i]) << 24; for (uint32_t j = 0; j < 8; j++) { if (crc & 0x80000000) { crc = (crc << 1) ^ 0x04C11DB7; } else { crc <<= 1; } } } return (uint16_t)(crc >> 16) & 0xFFFF; } ``` 这个bootloader程序的功能比较简单,可以接收通过串口发送的数据,写入到flash中。同时,当接收到应用程序标志码时,会跳转到应用程序的入口地址。注意,这里的bootloader程序大小应该小于应用程序的大小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值