|
以前只弄过一段时间模拟电路,对C语言和单片机的了解还是很久很久以前的事了。目前没啥事,闲着,想捡起来重新学习一下单片机,还没学几个月,很多地方一知半解,小白白。
最近尝试着用STC8H8K64U-LQFP32做一个简单的控制板,大概思路就是扫描按键、结合ADC分析,然后输出几个继电器。后来想着把几个模拟量用一个专门的IC去测量,STC8H就只定期用串口2读取这个测量IC的数据就可以了,各司其职。
前期的按键、LCD、ADC都在开发板和洞洞板调试通过了,最后遗留这个测量IC,封装比较小不好用洞洞板手焊,就直接打了几个样,想着最后来调试这个串口2。
好了,猜对了,理所当然的,就是这个串口2搞不定了,真是个忧伤的故事。忧伤啊!
这个也是我个人的短板,以前从没接触过通信方面的东西,折腾了几天,搞不定了,厚着脸皮上来求教。
已经考虑了下次打样换个方案,直接用STC8H测量所有的ADC,但有点不死心,因为这次这点问题都放弃了,后面肯定还要碰到类似问题。可能我认为绕不过的问题,在大佬眼中就是一句话的事。
谢谢了!
谢谢各位大佬帮我看看下面的程序。基本上是拷的手册的范例或者ISP串口小工具计算器。
程序运行到串口2发送字节的时候,就卡住了,不进中断,也就没办法给busy清零,可能:意味着发送没有完毕,没有进入中断,或者发送失败,一直发送中?
因为至少要发送2个字节,就算busy初始为0,发送了第一个字节后,如果不进中断清零,第二个字节就会卡在while(busy);
目前尝试过的有,没办法了,瞎折腾了:
1、改变中断优先级,设为最高3级。
2、外置上拉10K电阻装上或者扒掉。
3、定时器开启、打开中断全部都放在初始化函数,或者放在其他地方
4、调整Uart2Send()中三条语句的顺序
5、buffer[4]数值长度调整
6、示波器探P1.1发现有定期循环的脉冲组
7、P1.0一直有高电平,无脉冲波形
8、尝试去掉busy
9、去掉所有的不相干的程序和功能,只留这个串2来测试
10、打了4块样,每一个都一样的情况,软件没问题的话,那就是硬件设计有误了。功能比较简单,就是简单的输入输出控制,STC部分直接拷的官版建议电路,对面的测量IC也是官版电路。因为本来就是打样回来测试的板在,所以该有的电阻电容官版建议的玩意一个不少。除了电压正负,两个IC之间就只有串口2根线了。
如果硬件有误的话,怎么测试判断呢?
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#define READ_ERROR 0
//IO定义部分,封成一个小函数,放在public
P_SW2 |= 0x80; //扩展寄存器XFR访问使能
P0M0 = 0x00; P0M1 = 0x00;
P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x0e; P2M1 = 0x00; //P2.1,P2.2,P2.3推挽
P3M1 = 0x00; P3M0 = 0x00;
P4M1 = 0x00; P4M0 = 0x00;
P5M1 = 0x00; P5M0 = 0x00;
P6M1 = 0x00; P6M0 = 0x00;
P7M1 = 0x00; P7M0 = 0x00;
P_SW2 |=0x00; //设置串口2为P1.0,P1.1
P1PU = 0x02; //本来P1.0,P1.1两个都做了10K上拉,现在调试没过,全扒了,对方的串口输出有上拉
P2DR &= ~0x0e; //P2.1,P2.2,P2.3强推挽
//全局变量、数组定义
u8 buffer[4]; //缓存返回的4字节数据
bit busy=0;
u8 wptr;
void Uart2_Init(void) //串口2初始化。4800bps@11.0592MHz
{
S2CON = 0x90; //D0,90都不影响我的忧伤。S2SM0模式1,9位数据可变波特率,REN置1可接受数据。B6为空,0xD0(1101 0000)或者0x90(1001 0000)
T2L = 0xC0;
T2H = 0xFD; //设置定时初始值
IP2H=0x01;
IP2=0x01; //串口2为最高优先级。设不设都不影响我搞不定。
busy=0;
wptr = 0x00;
AUXR |= 0x04; //1T模式。04,10合体也无法让心情好转
AUXR |= 0x10; //定时器2开始计时,T2R置1,T2_C/T置0,用作定时器
}
void Uart2Isr() interrupt 8 //串口2中断函数
{
if (S2CON & 0x02) //检测串口2发送完成中断请求标志S2TI是否置1
{
S2CON &= ~0x02; //S2TI清零
busy=0; //挺闲的
}
if (S2CON & 0x01) //检测串口2接收完成中断请求标志S2RI是否置1
{
S2CON &= ~0x01; //S2RI清零
buffer[wptr++] = S2BUF; //把接收的数据依次放入数组
wptr &= 0x03; //限定4字节长度,避免溢出。
}
}
void Uart2Send(u8 dat) //发送1个字节
{
while(busy); //出问题的地方。会一直卡在此处循环,不进中断给busy清零,意味着发送没有完毕?没有进入中断?此处应该插个斗志昂扬的BGM循环播放。
busy=1;
S2BUF=dat; //此条放哪里都改变不了结局,欧耶!
}
u32 read_IC_dat(u8 address)
{
u8 CMD=0;
u8 CHECKSUM=0;
u32 read_value=0;
CMD=0x7F&address; //CMD的B7置0,其余不变
Uart2_Init(); //串口2初始化
IE2 = 0x01; //ES2置1,允许串行口2中断,ET2置0,禁止T2中断,其余全部置0禁止
EA=1; //打开总中断
Uart2Send(0x6A); //发送HEAD字节
Uart2Send(CMD); //发送命令
delay_ms(5); //延时,等待接收数据,放在buffer数组。要不要延时都不行。
CHECKSUM=~(0x06A+CMD+buffer[0]+buffer[1]+buffer[2]);//校验计算
if(CHECKSUM==buffer[3]) //buffer[3]为接收到的校验和
{
read_value=(buffer[0]<<16)|(buffer[1]<<8)|buffer[2];
return read_value;
}
else return READ_ERROR;
}
void main(void)//主函数
{
//略
//主函数就是循环扫描IO口输入按键和ADC,输出几个继电器控制,并定时通过串口2读取IC值到LCD显示,并辅助MCU判断和警告。
}
|
|