因为这款单片机没有硬件串口,所以需要我们自己做软件模拟串口。
用PA3作为RX,因为PA3可以作为外部输入中断EXTI1。
本人首先用轮询的方式查PA3是否从高电平跳变到低电平(起始信号),但是因为还有别的业务逻辑,导致查询到低电平的时候,不能确定此时低电平过了多少us,导致后续数据采样时间点不正确, 实时性较差。
改用中断了以后问题解决。
GPIO初始化代码如下
void Ny8b072a_Gpio_Init(void)
{
AWUCON = C_PA1_Wakeup; // Enable PA1 input change wakeup function
IOSTA = C_PA0_Input | C_PA1_Input | C_PA2_Input | C_PA3_Input | C_PA6_Input | C_PA7_Input ; // set PA0/1/3/6/7 to input mode
APHCON = (unsigned char)~( C_PA0_PHB | C_PA1_PHB | C_PA2_PHB| C_PA3_PHB | C_PA6_PHB | C_PA7_PHB ); // Enable PA0/1/3/6/7 Pull-High Resistor,others disable
PORTA = 0x20; // PA5 output high
//PA3
INTEDG = C_INT1_En | C_INT1_FallingEdge; // External interrupt 1 will be set while rising edge occurs on pin PA4
INTE = C_INT_EXT1 | C_INT_PABKey; // Enable External interrupt & PortB input change interrupt
BWUCON = C_PB5_Wakeup; // Enable PB5 input change wakeup function
IOSTB = C_PB5_Input | C_PB7_Input; // Set PB5/7 to input mode,others set to output mode
BPHCON = (unsigned char)~( C_PB5_PHB | C_PB7_PHB);
PORTB = 0x0F; // PB0/1/2/3 output high
IOSTC = C_PC_Output;
PORTC = 0x03; // PC0/1 output high
CPHCON = (unsigned char)~( C_PC0_PHB | C_PC1_PHB);
}
用了休眠功能,EXTI也可以唤醒。
中断里面接收代码如下
volatile unsigned int g_i = 0;
unsigned char g_uart_rx_length = 0;
unsigned char g_uart_rx_buff[13] = {0};
//! interrupt service routine
void isr(void) __interrupt(0)
{
if(INTFbits.INT1IF)
{
App_Delay_Us(26); //消抖52us
//起始信号
if(0 == REMOTE_RX_IO)
{
//INTEDG = 0; //PA4 is gpio
while(1)
{
for(g_i = 0; g_i < 8; g_i++)
{
g_uart_rx_buff[g_uart_rx_length] >>= 1;
App_Delay_Us(59); //104US
if(1 == REMOTE_RX_IO)
{
g_uart_rx_buff[g_uart_rx_length] |= 0x80;
}
}
App_Delay_Us(59); //104US
// 结束信号
if(1 == REMOTE_RX_IO)
{
if ( ('\n' == g_uart_rx_buff[g_uart_rx_length]) || (12 == g_uart_rx_length ) )
{
//INTEDG = C_INT1_En | C_INT1_FallingEdge; // External interrupt 0 will be set while rising edge occurs on pin PA4
//INTE = C_INT_EXT1; // Enable External interrupt & PortB input change interrupt
INTF = (unsigned char)~(C_INT_EXT1); // Clear INT0IF(External interrupt 0 flag bit)
return;
}
else
{
g_uart_rx_length++;
//wait for new start
while (1 == REMOTE_RX_IO);
App_Delay_Us(26);
}
}
else
{
//INTEDG = C_INT1_En | C_INT1_FallingEdge; // External interrupt 0 will be set while rising edge occurs on pin PA4
//INTE = C_INT_EXT1; // Enable External interrupt & PortB input change interrupt
INTF = (unsigned char)~(C_INT_EXT1); // Clear INT0IF(External interrupt 0 flag bit)
return;
}
}
}
else
{
INTF = (unsigned char)~(C_INT_EXT1); // Clear INT0IF(External interrupt 0 flag bit)
return;
}
}
}
//@16M 2T 2.5us
//App_Delay_Us(26); //52US
//App_Delay_Us(59); //104US
void App_Delay_Us(unsigned int count)
{
for(; count > 0; count--);
}
波特率9600 每一bit的时间是1/9600=104us,所以两个延时一个是52us一个是104us
延时函数是用示波器看过的,这里配置的是16M 2T
TX因为用不上所有没有去实现,不过思路是相同的,把IO口改为输出即可。