第一部分:系统设计遇到的问题
1、看不懂F28335如何控制数码管的位选与段选。
2、看不懂AD转换的参考电压与输入电压怎么调节的。
3、看不懂SPI如何设置并进行数据发送的。
欲知问题如何解决,请继续看……
第二部分:系统设计正文
一、系统设计方案
二、详细设计
1、硬件设计
I、AD转换原理
如图所示,参考电压(采用运算放大器实现)
,输入电压由滑动变阻器控制,这样,AD端输入电压即为
,经ADC后,转换结果由数码管显示。可通过调节可调变阻器改变其值,相应的AD转换结果也会得到改变,数码管显示也会改变。
II、数码管显示原理
如图为4位数码管显示原理图,采用共阳极连接方法,即可通过将GPIO70、GPIO71、GPIO72、GPIO73置1来控制数码管的位选(1为选择此位);数码管的段码输入由串行输入、并行输出的74HC164决定。选取F28335的GPIO54-SPISOMI作为74HC164的数据输入端,GPIO56-SPICLK作为74HC164的时钟输入端。SPICLK每经过一次上升沿跳变,74HC164锁存数据就右移一位(方向QA-QH),所以SPISOMI数据输出端输出数据时,数据传送采用高位到低位的方式。
下图为74HC164的时序图:
SPI结合74HC164实例:
A、设置SPI下降沿触发,至少8位数据传输以及波特率。
B、设置SPI的FIFO,禁止SPI中断。
2、软件设计
三、源代码
1、全局变量、函数声明等初始化
/*****************宏定义数码管位选 IO 接口**********************/
#defineSET_BIT4GpioDataRegs.GPCSET.bit.GPIO70 = 1//与外设板 8_LEDS 端子的 IO70 对应
#defineRST_BIT4GpioDataRegs.GPCCLEAR.bit.GPIO70 = 1//与外设板 8_LEDS 端子的 IO70 对应
#defineSET_BIT3 GpioDataRegs.GPCSET.bit.GPIO71 = 1//与外设板 8_LEDS 端子的 IO71 对应
#defineRST_BIT3GpioDataRegs.GPCCLEAR.bit.GPIO71 = 1//与外设板 8_LEDS 端子的 IO71 对应
#defineSET_BIT2 GpioDataRegs.GPCSET.bit.GPIO72 = 1//与外设板 8_LEDS 端子的 IO72 对应
#defineRST_BIT2GpioDataRegs.GPCCLEAR.bit.GPIO72 = 1//与外设板 8_LEDS 端子的 IO72 对应
#defineSET_BIT1 GpioDataRegs.GPCSET.bit.GPIO73 = 1//与外设板 8_LEDS 端子的 IO73 对应
#defineRST_BIT1GpioDataRegs.GPCCLEAR.bit.GPIO73 = 1//与外设板 8_LEDS 端子的 IO73 对应
/****************************函数申明*************************/
voiddelay(Uint32t);//延时函数
voidDisData_Trans(Uint16data);//转换结果拆分成四个1位数函数
voidSellect_Bit(Uint16i);//数码管位选函数
voidInit_LEDS_Gpio(void);//数码管初始化
voiddelay_loop(void);//延时函数
voidspi_xmit(Uint16a);//SPI数据传送函数
voidspi_fifo_init(void);//SPI_fifo初始化
voidspi_init(void);//SPI初始化
/**********************定义相关变量***********************/
unsignedcharmsg[10]=;//段码:0~9
unsignedcharDisData_Bit[4] = ;//存放拆分后的四位数字
Uint16DisData = 0;//显示的数字
Uint16Loop = 0;//位选控制
/***************全局变量定义****************/
Uint16showdata;
/***************ADC startparameters****************/
#defineADC_MODCLK 0x5// HSPCLK = SYSCLKOUT/2*ADC_MODCLK2 = 150/(2*4) = 15MHz
// for 60 MHz devices: HSPCLK = 60/(2*4) = 7.5 MHz
#defineADC_CKPS 0x1// ADC module clock = HSPCLK/2*ADC_CKPS = 15MHz/(1*2) = 7.5MHz
#defineADC_SHCLK 0xf// S/H width in ADC module periods = 16 ADCclocks
#defineAVG 100// Average sample limit
#defineZOFFSET 0x00// Average Zero offset
#defineBUF_SIZE 2048// Sample buffer size
// Global variable for thisexample
Uint16SampleTable[BUF_SIZE];
2、主函数初始化
Uint16i;
Uint32Sum=0;
Uint32Vin;
Uint16sdata;// 发送数据
// Step 1. Initialize SystemControl:
// PLL, WatchDog, enablePeripheral Clocks
// This example function isfound in the DSP280x_SysCtrl.c file.
InitSysCtrl();
// Specific clock setting forthis example:
EALLOW;
SysCtrlRegs.HISPCP.all= ADC_MODCLK;// HSPCLK = SYSCLKOUT/(2*ADC_MODCLK)=15MHZ
EDIS;
// Step 2. Initialize GPIO:
// This example function isfound in the DSP280x_Gpio.c file and
// illustrates how to set theGPIO to it's default state.
// InitGpio(); // Skipped for this example
// 次函数在DSP280x_Spi.c文件里面
InitSpiaGpio();//开发板使用SPIa
Init_LEDS_Gpio();
// Step 3. Clear allinterrupts and initialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize the PIE controlregisters to their default state.
// The default state is allPIE interrupts disabled and flags
// are cleared.
// This function is found inthe DSP280x_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts andclear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vectortable with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate theentire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines arefound in DSP280x_DefaultIsr.c.
// This function is found inDSP280x_PieVect.c.
InitPieVectTable();
// 步骤 4.初始化片内外设:
InitAdc();// For this example,initthe ADC
spi_fifo_init();// 初始化Spi的FIFO
spi_init();// 初始化SPI
// Specific ADC setup forthis example:
AdcRegs.ADCTRL1.bit.ACQ_PS= ADC_SHCLK;//设置采样窗口时间:(15+1)*ADCCLK
AdcRegs.ADCTRL3.bit.ADCCLKPS= ADC_CKPS;//ADC内核时钟分频:HSPCLK/2=6.25MHZ
AdcRegs.ADCTRL1.bit.SEQ_CASC= 1;// 1选择级联模式
AdcRegs.ADCCHSELSEQ1.bit.CONV00= 0x0;//通道选择ADCAIN0
AdcRegs.ADCTRL1.bit.CONT_RUN= 1;// 设置为连续运行
3、SPI初始化
//初始化SPI函数
voidspi_init()
{
SpiaRegs.SPICCR.all=0x004F;// SPI软件复位, 极性位为1(下降沿发送数据), 每次移进和移出16位字长度;禁止SPI内部回送(LOOKBACK)功能;
SpiaRegs.SPICTL.all=0x0006;// 使能主机模式,正常相位,使能主机发送,禁止接收溢出中断,禁止SPI中断;
SpiaRegs.SPIBRR=0x007F;//SPI波特率=25M/128 =195.3KHZ;SpiaRegs.SPICCR.all=0x00CF;//停止SPI软件复位准备接收或发送;禁止回送模式;
SpiaRegs.SPIPRI.bit.FREE= 1;// 自由运行
}
//初始化SPI FIFO
voidspi_fifo_init()
{
SpiaRegs.SPIFFTX.all=0xE040;//使能FIFO;清除发送中断标志位;禁止FIFO发送中断;
//发送中断级别定义为0;
SpiaRegs.SPIFFRX.all=0x204f;//清除FF溢出标志位;清除溢出接受中断标志位;禁止
//FF接受中断;接受中断级别为16;
SpiaRegs.SPIFFCT.all=0x0;//SPITXBUF到移位寄存器传送不延迟;
}
4、SPI发送数据子函数
voidspi_xmit(Uint16a)
{
SpiaRegs.SPITXBUF=a;
}
5、数码管GPIO初始化、位选函数、数据拆分函数
/************数码管位选 IO 接口初始化****************/
voidInit_LEDS_Gpio(void)
{
EALLOW;
GpioCtrlRegs.GPCPUD.bit.GPIO70= 0;// Enablepullupon GPIO11
GpioDataRegs.GPCSET.bit.GPIO70= 1;// Load output latch
GpioCtrlRegs.GPCMUX1.bit.GPIO70= 0;// GPIO16 = GPIO
GpioCtrlRegs.GPCDIR.bit.GPIO70= 1;// GPIO16 = output
GpioCtrlRegs.GPCPUD.bit.GPIO71= 0;// Enablepullupon GPIO11
GpioDataRegs.GPCSET.bit.GPIO71= 1;// Load output latch
GpioCtrlRegs.GPCMUX1.bit.GPIO71= 0;// GPIO16 = GPIO
GpioCtrlRegs.GPCDIR.bit.GPIO71= 1;// GPIO16 = output
GpioCtrlRegs.GPCPUD.bit.GPIO72= 0;// Enablepullupon GPIO11
GpioDataRegs.GPCSET.bit.GPIO72= 1;// Load output latch
GpioCtrlRegs.GPCMUX1.bit.GPIO72= 0;// GPIO17 = GPIO
GpioCtrlRegs.GPCDIR.bit.GPIO72= 1;// GPIO17 = output
GpioCtrlRegs.GPCPUD.bit.GPIO73= 0;// Enablepullupon GPIO11
GpioDataRegs.GPCSET.bit.GPIO73= 1;// Load output latch
GpioCtrlRegs.GPCMUX1.bit.GPIO73= 0;// GPIO19 = GPIO
GpioCtrlRegs.GPCDIR.bit.GPIO73= 1;// GPIO19 = output
EDIS;
}
/**********数码管位选函数(从低位到高位扫描)************/
voidSellect_Bit(Uint16i)
{
switch(i)
{
case0:
RST_BIT4;//关断数码管第四位
SET_BIT1;//选通数码管第一位
break;
case1:
RST_BIT1;//关断数码管第一位
SET_BIT2;//选通数码管第二位
break;
case2:
RST_BIT2;//关断数码管第二位
SET_BIT3;//选通数码管第三位
break;
case3:
RST_BIT3;//关断数码管第三位
SET_BIT4;//选通数码管第四位
break;
default:
break;
}
}
/*****************************************************************************************************/
/******** 拆分要显示的四位数保存到数组DisData_Trans【】*******/
voidDisData_Trans(Uint16data)
{
DisData_Bit[3] = data / 1000;//千位数
DisData_Bit[2] = data % 1000 / 100 ;//百位数
DisData_Bit[1] = data % 100 / 10;//十位数
DisData_Bit[0] = data % 10;//个位数
}
6、主循环
for(;;)
{
for(i=0; i
{
while(AdcRegs.ADCST.bit.INT_SEQ1== 0) {}//等待中断
AdcRegs.ADCST.bit.INT_SEQ1_CLR= 1;
SampleTable[i] =((AdcRegs.ADCRESULT0>>4) );
}
for(i=0;i
{
Sum+=SampleTable[i];//采样值相加
Sum=Sum/2;//取平均
}
//输入电压和AD值之间的关系Vin/Sum=3/4096;
Vin=Sum*3*10000/4096;//将输入电压放大100倍,以便于第2位有效小数的四舍五入计算;
if(Vin%10>=5)//最后一位整数>=5时,要五入;
showdata=Vin/10+1;
else
showdata=Vin/10;//要四舍;
for(i=0;i
{
DisData_Trans(showdata);//拆分四位数
for(Loop=0;Loop
{
Sellect_Bit(Loop);//选择要扫描的数码管位
if(Loop==3)
spi_xmit(msg[DisData_Bit[Loop]]+0x80);//数码管第四位添加小数点
else
spi_xmit(msg[DisData_Bit[Loop]]);//串行输出要显示的数字
delay(25000);//延时配合人眼反应时间
}
}
}
}
四、系统设计实物(附视频)
领取专属 10元无门槛券
私享最新 技术干货