|
|
发表于 2026-5-28 09:41:58
|
显示全部楼层
#include "config.h"
#include "UART1.h"
/************* 功能说明 **************
用户请先别修改程序, 直接下载"ADC.hex"测试.
下载时选择主频24MHZ. 测试时, 电脑的串口助手设置115200,8,n,1.
本程序演示使用开天斧三.1的P1.5做12位ADC输入过采样得到16位ADC结果, 通过串口1(P3.1)发送给上位机,波特率115200,8,n,1.
打开串口助手开始接收, 再打开"STC调试助手"中的"7段数码管"即可看到结果.
******************************************/
/************* 本地常量声明 **************/
#define ADC_CHN 5 /* 定义ADC通道 */
/************* IO口定义 **************/
/************* 本地变量声明 **************/
u16 adc; // 当前完成的ADC值, 用于过程计算, 不传递结果数值, 用户层不可见.
u32 adc_sum; // ADC累加和, 中断使用的变量, 用户层不可见
bit B_ADC_OK; // ADC已测量计算OK.
u16 adc_cnt; // ADC已转换次数, 中断使用, 用户层不可见.
u16 adc_16bit; // 测量的16位ADC值
u8 trian_cnt;
/************* 本地函数声明 **************/
void ADC_config(void);
u8 Timer0_Config(u8 t, u32 reload); //t=0: reload值是主时钟周期数, t=1: reload值是时间(单位us)
/**************** 外部函数声明和外部变量声明 *****************/
/**********************************************/
void main(void)
{
u16 j;
P0M1 = 0; P0M0 = 0; //设置为准双向口
P1M1 = 0; P1M0 = 0; //设置为准双向口
P2M1 = 0; P2M0 = 0; //设置为准双向口
P3M1 = 0; P3M0 = 0; //设置为准双向口
P5M1 = 0; P5M0 = 0; //设置为准双向口
ADC_config(); //初始化ADC
Timer0_Config(0, MAIN_Fosc / 12800); //t=0: reload值是主时钟周期数, (中断频率)
P1n_push_pull(Pin1); // P1.1推挽输出方波经过RC转三角波
EA = 1;
UART1_config(115200UL, 1, 0); // brt: 通信波特率, timer=2: 波特率使用定时器2, 其它值: 使用Timer1做波特率. io=0: 串口1切换到P3.0 P3.1, =1: 切换到P3.6 P3.7, =2: 切换到P1.6 P1.7.
while (1)
{
if(B_ADC_OK) //ADC转换完成
{
B_ADC_OK = 0;
UART1_PrintString("7SEGS"); //7段数码管命令头
TX1_write2buff(0x00);
TX1_write2buff(0x00);
TX1_write2buff(0x00);
j = adc_16bit;
// j = (u16)((float)j*1.001f); //增益校正, 根据实际情况使用
TX1_write2buff( j/10000 + '0');
TX1_write2buff((j%10000)/1000 + '0');
TX1_write2buff((j%1000)/100 + '0');
TX1_write2buff((j%100)/10 + '0');
TX1_write2buff( j%10 + '0');
TX1_write2buff(0x0);
}
}
}
/**********************************************/
//========================================================================
// 函数: void ADC_config(void)
// 描述: ADC配置函数.
// 参数: None
// 返回: none.
// 版本: V1.0, 2021-12-23
//========================================================================
#define ADC_POWER (1<<7) /* 打开ADC电源 */
#define ADC_START (1<<6) /* 自动清0 */
#define ADC_FLAG (1<<5) /* 软件清0 */
#define ADC_EPWMT (1<<4) /* 允许PWM触发ADC */
#define RES_FMT (1<<5) /* ADC结果格式 0: 左对齐, ADC_RES: D9 D8 D7 D6 D5 D4 D3 D2, ADC_RESL: D1 D0 0 0 0 0 0 0 */
/* 1: 右对齐, ADC_RES: 0 0 0 0 0 0 D9 D8, ADC_RESL: D7 D6 D5 D4 D3 D2 D1 D0 */
#define ADC_SPEED 3 /* 0~15, ADC时钟 = SYSclk/2/(n+1) */
#define CSSETUP (1<<7) /* 0~1, ADC通道选择时间 0: 1个ADC时钟, 1: 2个ADC时钟, 默认0(默认1个ADC时钟) */
#define CSHOLD (1<<5) /* 0~3, ADC通道选择保持时间 (n+1)个ADC时钟, 默认1(默认2个ADC时钟) */
#define SMPDUTY 20 /* 10~31, ADC模拟信号采样时间 (n+1)个ADC时钟, 默认10(默认11个ADC时钟) */
/* ADC转换时间: 10位ADC固定为10个ADC时钟, 12位ADC固定为12个ADC时钟. */
void ADC_config(void)
{
P_SW2 |= 0x80; //访问XSFR
P1n_pure_input((1<<ADC_CHN)); //设置要做ADC的IO做高阻输入
ADC_CONTR = ADC_POWER | ADC_EPWMT | 0; //ADC on + channel
ADCCFG = RES_FMT + ADC_SPEED;
ADCTIM = CSSETUP + CSHOLD + SMPDUTY;
EADC = 1; //允许ADC中断
}
//========================================================================
// 函数: void ADC_ISR (void) interrupt ADC_VECTOR
// 描述: ADC中断函数.
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2018-4-1
// 备注:
//========================================================================
void ADC_ISR (void) interrupt ADC_VECTOR
{
ADC_CONTR &= ~ADC_FLAG; //清除中断标志
adc = (u16)ADC_RES * 256 + (u16)ADC_RESL; //读ADC结果
adc_sum += adc; //adc累加和
if(++trian_cnt == 8) //产生方波, 经过RC转成三角波
{
trian_cnt = 0;
P11 = ~P11;
}
// if(++adc_cnt == 256) // 累加256次完成, 时间20ms
if(++adc_cnt == 2048) // 累加2048次完成, 时间160ms
{
P11 = 0;
adc_cnt = 0;
trian_cnt = 0;
B_ADC_OK = 1; //标志已完成一次过采样, 20ms
// adc_16bit = adc_sum/16; //ADC结果
adc_16bit = adc_sum/128; //ADC结果
adc_sum = 0;
}
}
//========================================================================
// 函数: void timer0_int (void) interrupt TIMER0_VECTOR
// 描述: timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2018-12-20
//========================================================================
void timer0_ISR (void) interrupt TIMER0_VECTOR
{
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = 0x80 | ADC_START | ADC_CHN; //启动ADC
}
//========================================================================
// 函数:u8 Timer0_Config(u8 t, u32 reload)
// 描述: timer0初始化函数.
// 参数: t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
// reload: 重装值.
// 返回: 0: 初始化正确, 1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-12-20
//========================================================================
u8 Timer0_Config(u8 t, u32 reload) //t=0: reload值是主时钟周期数, t=1: reload值是时间(单位us)
{
TR0 = 0; //停止计数
if(t != 0) reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL); //重装的是时间(us), 计算所需要的系统时钟数.
if(reload >= (65536UL * 12)) return 1; //值过大, 返回错误
if(reload < 65536UL) AUXR |= 0x80; //1T mode
else
{
AUXR &= ~0x80; //12T mode
reload = reload / 12;
}
reload = 65536UL - reload;
TH0 = (u8)(reload >> 8);
TL0 = (u8)(reload);
ET0 = 1; //允许中断
PT0 = 1; //高优先级中断
TMOD = (TMOD & ~0x03) | 0; //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
TR0 = 1; //开始运行
return 0;
}
|
|