📄 fjv14.c
字号:
//m8L,4M晶振,波特率2400
#include "iom8v.h"
#include"macros.h"
#include"stdio.h"
//控制DA的cs位
#define set_cs PORTB |= (1<<PB2)
#define clr_cs PORTB &= 0b11111011
#define IO_PB0 0x00
#define IO_PB1 0x01
#define IO_PB4 0x04
#define IO_PD5 0x05
#define IO_PD6 0x06
#define IO_PD7 0x07
//定义全局变量-------------------------------
unsigned int AD_value10;//ad采集值10位。
//------------------------------------------
unsigned int ADC_filter(void);
void init_devices(void);
unsigned char USART_Recive(void);
void USART_Transmit(unsigned char tdata);
void ADC_Start(void);
unsigned int ADC_Value (unsigned char adc_channel);
void DAC_5617_10(unsigned char dac_dataH,unsigned char dac_dataL,unsigned char dac_channel);
void SPI_Transmit(unsigned char dac_data);
unsigned char SPI_Compare(unsigned char data,unsigned char mark);
void delay_1ms(void);
unsigned char Strcat(unsigned char s1,unsigned char s2);
void IO_out(unsigned char IO_data,unsigned char IO_channel);
unsigned char IO_in (unsigned char IO_channel);
/**************************************************************************/
void port_init(void)
{
PORTB = 0xFF;//确保复位电平是确定的,输入、上拉
DDRB = 0x00;
PORTC = 0xFF;
DDRC = 0x00;
PORTD = 0xFF;
DDRD=0x00;
}
/********************************************************************/
//Watchdog initialize
// prescale: 512K 0.52s
void watchdog_init(void)
{
WDR(); //this prevents a timout on enabling
WDTCR = 0x0D; //WATCHDOG ENABLED - dont forget to issue WDRs
}
/*********************************************************************/
//关闭看门狗
void WDT_off(void)
{
_WDR();
WDTCR |= (1<<WDCE)|(1<<WDE);
WDTCR = 0x00;
}
/**************************************************************************/
void uart0_init(void)
{
UCSRB=(1<<RXEN)|(1<<TXEN);//发送接收使能
UCSRC=(1<<UMSEL);//选择异步发送模式
UBRRL = 0x33;//设置波特率低位4m4800
UBRRH = 0x00; //设置波特率高位
UCSRA = 0x18; //接收、发送数据
UCSRC =(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//8位数据+1位STOP位
}
/************************************************************************/
void spi_init(void)
{
//PB2为CS端。PB3为MOSI端。PB5为SCK端。
// PORTB=(1<<PB2)|(1<<PB3)|(1<<PB5);//SPI端口初始化.慎用<<置1。将会影响其他位。
DDRB= (1<<DDB2)|(1<<DDB3)|(1<<DDB5);//SPI端口初始化
SPSR=0x01;//SPI状态寄存器初始化
SPCR=0x58; //SPI使能
}
/*************************************************************************/
//ADC initialize
// Conversion time: 52uS
void adc_init(void)
{
PORTC =(0<<PC0)|(0<<PC1)|(0<<PC2)|(0<<PC3) ;//关闭上拉电阻
ACSR = 0x00;//与模拟比较器控制
//ACSR =(1<<ACD);//关闭模拟比较器
ADMUX=0x00;//设定AD选择寄存器,片外基准。ch1通道(对应芯片ADC0)。数据右对齐。
ADCSRA = 0x00; //disable adc
ADCSRA=(1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(0<<ADPS1) ;//16分频,使能AD,开启中断。还没开始转换。
}
/*************************************************************************/
#pragma interrupt_handler adc_isr:15
void adc_isr(void)
{
//conversion complete, read value (int) using...
AD_value10 = ADCL; //Read 8 low bits first (important)
AD_value10|=(unsigned int)ADCH << 8; //read 2 high bits and shift into top byte
}
/*************************************************************************/
void init_devices(void)
{
CLI(); //关闭所有中断
port_init();//端口初始化
watchdog_init();
uart0_init();//串行通信初始化
adc_init();//AD初始化
spi_init();//SPI初始化
MCUCR = 0x10;//ADC噪声抑制模式。
GICR = 0x00;//关外部中断
SEI();
}
/**************************************************************************/
/**************************************************************************/
void main( )
{
unsigned char charry[5];
unsigned char y;
unsigned char temp8;
unsigned int temp10;//接收10位的数据,如AD等。
unsigned int i;
unsigned int m;
init_devices();//初始化
while(1)
{
charry[0]=0;//初始化
charry[1]=0;
charry[2]=0;
charry[3]=0;
charry[4]=0;
y=0;
temp8=0;
temp10=0;
m=0;
WDT_off();//等待第一个接收数据。
y=USART_Recive();
charry[0]=y;//接收数据
watchdog_init();//打开看门狗,防止串行数据中断而无限等待。
for(i=1;i<5;i++)
{
y=USART_Recive();
charry[i]=y;//接收数据
}
if (charry[0]==0x55)
{
//功能选择判断
switch (charry[1])
{
case 0x03: //如果为00则启动IO输出
IO_out(charry[3],charry[2]); //确定输出数据和端口
break;
case 0x02: //如果为00则启动IO输入
temp8=IO_in(charry[2]);//启动IO转换,确定通道数。
USART_Transmit(temp8);//启动串口发送IO数据(第四位)
//USART_Transmit(0x00);//启动串口发送IO数据(第五位)
break;
case 0x01://如果为01则启动AD转换
temp10=ADC_Value(charry[2]);//启动AD转换,确定通道数。
m=temp10;
temp8=(unsigned char)(m>>8);
USART_Transmit(temp8);//启动串口发送数据(高8位)
temp8=(unsigned char)temp10;
USART_Transmit(temp8);//启动串口发送数据(低8位)
break;
case 0x10://如果为10则启动DA转换
DAC_5617_10(charry[3],charry[4],charry[2]); //启动DA5716
break;
case 0x11://如果为11则先启动DA再启动AD转换
DAC_5617_10(charry[3],charry[4],0x01); //启动DA5716
asm("NOP");
temp10=ADC_Value(0x01); //启动AD转换,AD/DA使用相同通道1。
m=temp10;
temp8=(unsigned char)(m>>8);
USART_Transmit(temp8);//启动串口发送数据(高8位)
temp8=(unsigned char)temp10;
USART_Transmit(temp8);//启动串口发送数据(低8位)
break;
default:break;
}
}
}
}
/**************************************************************************/
//串口接收数据
unsigned char USART_Recive(void)
{
unsigned char y;
//等待接收数据
while(!(UCSRA&(1<<RXC)));
y=getchar(); //接收数据
return y;
}
/*******************************************************************/
//串口发送数据
void USART_Transmit(unsigned char tdata)
{
//等待数据寄存器空
UDR=tdata;
while(!(UCSRA&(1<<UDRE)))
;
}
/******************************************************************/
/*******************************************************************
函数功能:AD数据、通道采集,10位精度。
入口参数:adc_channel通道选择。
出口参数:AD采集的数据
说明:此处可以加入中值滤波程序。使用ADC降噪中断方式
*******************************************************/
unsigned int ADC_Value (unsigned char adc_channel)
{
unsigned int temp;
temp=0;
switch (adc_channel)
{
case 0x01: //如果为00则启动CH1通道
ADMUX=0x00;//寄存器后4位对应通道。0代表CH1通道。
temp=ADC_filter();
break;
case 0x02: //如果为01则启动CH2通道
ADMUX=0x01;//寄存器后4位对应通道。1代表CH2通道。
temp=ADC_filter();
break;
case 0x03: //如果为10则启动CH2通道
ADMUX=0x02;//寄存器后4位对应通道。2代表CH3通道。
temp=ADC_filter();
break;
case 0x04: //如果为00则启动CH1通道
ADMUX=0x03;//寄存器后4位对应通道。3代表CH4通道。
temp=ADC_filter();
break;
default:break;
}
return temp;
}
/*******************************************************************
函数功能:首先采集数据,然后三点中值滤波。同时解决第一次采集不准问题。
入口参数:无
出口参数:outdata,滤波后的结果
说明:
*******************************************************/
unsigned int ADC_filter(void)
{
unsigned int a;
unsigned int outdata;
unsigned int temp[2];
temp[0]=0;
temp[1]=0;
temp[2]=0;
ADC_Start();//丢弃第一次结果。
AD_value10=0;//采集数据前先将变量清零。避免上一次的干扰。
ADC_Start();
temp[0]=AD_value10;//AD转换结果
ADC_Start();
temp[1]=AD_value10;//AD转换结果
ADC_Start();
temp[2]=AD_value10;//AD转换结果
//下面的程序让数组从小到大排列
if (temp[0]>temp[1])
{
a=temp[1];
temp[1]=temp[0];
temp[0]=a;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -