haiyang201 发表于 2025-5-29 13:39:44

jpknecoq 发表于 2025-5-29 10:36
你好,我硬件用的8H,能帮忙指出有哪些区别啊,我固定输出0x5A是没问题的,但是输出的ADC值不太对,所以 ...
8h多是12位的,8g是10位的,第一采集的丢掉不要

jpknecoq 发表于 2025-5-29 14:45:59

已经调通了,STC8H只作为主机通过SPI发出P3.5和P3.6的ADC数据,数据里加了一些包头,源码:


/*------------------------------------------------------------------*/
/* --- STC MCU ADC + SPI with 16-bit Combined Data Format -----------*/
/*------------------------------------------------------------------*/

#define MAIN_Fosc      11059200L
#define FILTER_LENGTH    16
#define SEND_INTERVAL    100

#include "STC8Gxxx.h"   //头文件见附件
#include "intrins.h"

/************* 协议定义 **************/
#define HEADER_A0    0x00A0
#define HEADER_A1    0x00A1
#define HEADER_A2    0x00A2
#define SYNC_WORD    0xAAAA

/************* 硬件配置 **************/
#define ADC_START    (1<<6)
#define ADC_FLAG   (1<<5)
#define ADC_CLK_DIV5

/************* 全局变量 **************/
u16 ADC_Raw = {0};
u16 ADC_Filtered = {0};
u8 filter_index = 0;
bit current_channel = 0;

/************* 函数声明 **************/
void System_Init(void);
u16 Get_ADC10bitResult(u8 channel);
void SPI_SendData(u16 dat);
void ADC_Filter_Process(void);
void Send_CompleteFrame(void);
void delay_us(u16 us);
void delay_ms(u16 ms);

/************* 主函数 **************/
void main(void)
{
    u16 send_counter = 0;
    System_Init();
   
    while(1)
    {
      if(current_channel == 0)
      {
            ADC_Raw = Get_ADC10bitResult(13);
            current_channel = 1;
      }
      else
      {
            ADC_Raw = Get_ADC10bitResult(14);
            current_channel = 0;
            filter_index = (filter_index + 1) % FILTER_LENGTH;
      }
      
      if(++send_counter >= SEND_INTERVAL)
      {
            send_counter = 0;
            ADC_Filter_Process();
            Send_CompleteFrame();
      }
      
      delay_us(100);
    }
}

/************* 延时函数实现 **************/
void delay_us(u16 us)
{
    while(us--)
    {
      _nop_(); _nop_(); _nop_(); _nop_();
      _nop_(); _nop_(); _nop_(); _nop_();
      /*
         * 对于11.0592MHz时钟:
         * 每个_nop_()执行1个机器周期(12个时钟周期)
         * 8个_nop_() ≈ 8*(12/11.0592) ≈ 8.68us
         * 实际使用时需要根据实测调整循环次数
         */
    }
}

void delay_ms(u16 ms)
{
    while(ms--)
    {
      delay_us(1000); // 近似1ms延时
    }
}

/************* 16位组合数据帧发送 (修正版)**************/
void Send_CompleteFrame(void)
{
    // 帧起始
    SPI_SendData(HEADER_A0);
    SPI_SendData(SYNC_WORD);
    SPI_SendData(SYNC_WORD + HEADER_A0);
   
    // 通道1数据(修正A1校验和)
    SPI_SendData(HEADER_A1);                  // 发送Header A1
    SPI_SendData(ADC_Filtered);            // 发送通道1数据
    SPI_SendData(HEADER_A1 + ADC_Filtered);// 关键修改: 使用HEADER_A1计算校验和
   
    // 通道2数据
    SPI_SendData(HEADER_A2);
    SPI_SendData(ADC_Filtered);
    SPI_SendData(HEADER_A2 + ADC_Filtered);
   
    delay_us(50); // 帧间延时
}

/************* SPI数据发送 **************/
void SPI_SendData(u16 dat)
{
    P12 = 0;                // 片选有效
    SPDAT = dat >> 8;       // 高字节
    while(!(SPSTAT & 0x80));
    SPSTAT = 0xC0;
   
    SPDAT = (u8)dat;      // 低字节
    while(!(SPSTAT & 0x80));
    SPSTAT = 0xC0;
    P12 = 1;                // 片选释放
    delay_us(10);         // 片选释放保持时间
}

/************* 系统初始化 **************/
void System_Init(void)
{
    // SPI初始化
    P1M1 &= ~0x3C;
    P1M0 |= 0x3C;
    P12 = 1;
    SPCTL = 0xF0;
    SPSTAT = 0xC0;
   
    // ADC初始化
    P3M0 &= ~0x60;
    P3M1 |= 0x60;
    ADC_CONTR = 0x80;
    ADCCFG = (1<<5) | ADC_CLK_DIV;
    P_SW2 |= 0x80;
    ADCTIM = 0x3F;
    P_SW2 &= ~0x80;
    delay_ms(10);         // 等待ADC稳定
}

/************* ADC采样函数 **************/
u16 Get_ADC10bitResult(u8 channel)
{
    ADC_RES = 0;
    ADC_RESL = 0;
    ADC_CONTR = 0x80 | ADC_START | channel;
    _nop_(); _nop_(); _nop_(); _nop_();
    while(!(ADC_CONTR & ADC_FLAG));
    ADC_CONTR &= ~ADC_FLAG;
    return ((u16)ADC_RES << 8) | ADC_RESL;
}

/************* 数据滤波处理 **************/
void ADC_Filter_Process(void)
{
    u32 sum0 = 0, sum1 = 0;
    u8 i;
   
    for(i=0; i<FILTER_LENGTH; i++)
    {
      sum0 += ADC_Raw;
      sum1 += ADC_Raw;
    }
   
    ADC_Filtered = sum0 / FILTER_LENGTH;
    ADC_Filtered = sum1 / FILTER_LENGTH;
}
页: 1 [2]
查看完整版本: 通过SPI发出两路ADC数据,通过FPGA读到的数据不对,请问为什么