sdk模板程序:ps_spi_adc128s and pl_spi_digtub - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

说明

  • 主要是这个程序架构非常吸引人:在2ms的scu_timer中断中,做按键检测和刷新digtub。
  • 在主程序的while循环中读取adc128s的值1024次,并做平均,并刷新digtub的framebuffer。
extern uint8_t Dig_Data[8][2];
extern uint8_t ADC_Channel;
static uint8_t i,Flag_200ms;	//200ms标志位

/**
  *****************************************************
  * @brief	私有定时器中断处理程序
  * @tag	本函数用来处理私有定时器中断,在内部加入用户程序即可
  *****************************************************
**/
void ScuTimer_IRQ_Handler(void *CallBackRef)
{
	/* ↓↓↓用户处理↓↓↓ */

    //每过200ms检测一次按键
    if (Flag_200ms < 100) {
    	Flag_200ms++;
    } else {
    	Flag_200ms = 0;
    	if((!PS_GPIO_GetPort(54)) && ADC_Channel < 7)
    		ADC_Channel++;
    	else if ((!PS_GPIO_GetPort(55)) && ADC_Channel > 0)
    		ADC_Channel--;
    }

    //每过2ms用SPI控制数码管显示第i位数据
	//PS_SPI_Transfer(&SPI1, 0, 0,Dig_Data[i], 2);
	AXI_SPI_Transfer(&AXI_SPI0, 0, NULL, Dig_Data[i], 2);
	if(i<8)
		i++;
	else
		i = 0;

	/* ↑↑↑结束处理↑↑↑ */
    XScuTimer_ClearInterruptStatus(&ScuTimer);
}
/**
  *****************************************************************************
  * 	使用按键S0和S1,切换ADC128S的8个通道,并在数码管显示检测到的电压值
  *****************************************************************************
  *
  * @File   : main.c
  * @By     : Sun
  * @Version: V1.1
  * @Date   : 2021 / 11 / 04
  * @Shop	: https://xiaomeige.taobao.com/
  * @Tag	: 由于ADC128S单次采集需收发16字节,SPI一次传输8字节,因此每次采集需要传输两次
  *****************************************************************************
**/

#include "ACZ702_Lib/COMMON.h"

//用于存储数码管的编码值,依次为0,1,2,3,4,5,6,7,8,9,-,.
uint8_t Seg_Code[12] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF,0x7F};

uint8_t Dig_Data[8][2] = {{0xC6,0x80},{0x89,0x40},{0xBF,0x20},{0xFF,0x10},
		{0x40,0x08},{0xC0,0x04},{0xC0,0x02},{0xC0,0x01}};//赋予初值,数码管编码CH0 0.000
uint8_t ADC_Channel = 0;		//设置ADC通道为INT0

int main()
{
	uint16_t i;
	uint8_t Set_Channel[2] = {0x00,0x00};	//存储发送的通道数据8*2=16bit
	uint8_t ADC_Raw_Data[2];				//存储读取的ADC原始数据8*2=16bit
	uint32_t ADC_Acc_Val;					//存储ADC累加值
	float ADC_Val;							//ADC电压值

	ScuGic_Init();	//初始化通用中断控制器
	//初始化SPI0设备,设为主机模式,低电平有效,片选信号后,第二个SCK边缘的数据有效
	PS_SPI_Init(&SPI0, XPAR_XSPIPS_0_DEVICE_ID, XSPIPS_CLK_PRESCALE_16, XSPIPS_MASTER_OPTION
				| XSPIPS_CLK_PHASE_1_OPTION
				| XSPIPS_CLK_ACTIVE_LOW_OPTION
				);
	//初始化SPI1设备,设为主机模式
	//PS_SPI_Init(&SPI1, XPAR_XSPIPS_1_DEVICE_ID, XSPIPS_CLK_PRESCALE_16, XSPIPS_MASTER_OPTION);
	AXI_SPI_Init(&AXI_SPI0, XPAR_SPI_0_DEVICE_ID, XSP_MASTER_OPTION);

	PS_GPIO_Init();	//初始化PS端的GPIO外设
	PS_GPIO_SetMode(54, INPUT, 0);	//初始化GPIO54,设置为输入
	PS_GPIO_SetMode(55, INPUT, 0);	//初始化GPIO55,设置为输入

	ScuTimer_Int_Init(2000);	//初始化定时器,设置为2000us启动定时器

	while (1) {
		ADC_Acc_Val = 0;	//ADC累加值清零
		Set_Channel[0] = ADC_Channel << 3;	//使用通道值计算设定值

		//ADC原始数据累加1024次
		for (i = 0;i < 1024;i++) {
			PS_SPI_Transfer(&SPI0, 0, ADC_Raw_Data, Set_Channel, 2);	//用SPI与ADC128S通信,收发2字节
			ADC_Acc_Val += ((ADC_Raw_Data[0] & 0x1F) << 8) + ADC_Raw_Data[1];	//ADC数值累加
		}

		ADC_Val = ADC_Acc_Val / 1024 * 3.3 / 4095 ;	//将累加值除以1024取平均值,然后使用公式换算为电压值

		Dig_Data[2][0] = Seg_Code[ADC_Channel];					//通道值
		Dig_Data[4][0] = Seg_Code[(int)ADC_Val] & 0x7F;			//电压整数位
		Dig_Data[5][0] = Seg_Code[(int)(ADC_Val * 10) % 10];		//电压值十分位
		Dig_Data[6][0] = Seg_Code[(int)(ADC_Val * 100) % 10];	//电压值百分位
		Dig_Data[7][0] = Seg_Code[(int)(ADC_Val * 1000) % 10];	//电压值千分位

		usleep(500000);	//每500ms更新一次数值
		printf("%d, %f, %f\r\n", ADC_Channel, ADC_Acc_Val/1024.0, ADC_Val);
	}
}