[XMG助力国产生态]
@XMGroupe.
本文介绍MC3172普通IO模拟UART
此驱动通过软件延时实现,目前9600波特率能够稳定运行。
内部RC高速时钟 192M
1.初始化代码
typedef enum _TX_STATE_{
eUART_TX_IDLE = 0, //发送空闲
eUART_TX_SEND = 1, //发送数送
}eTX_STATE;
typedef struct _eUART_TX_{
eTX_STATE tx_state; //发送状态
u32 bound; //波特率
u8 nstop; //停止位数
}eUART_TX;
typedef enum _RX_STATE_{
eUART_RX_IDLE = 0, //接收空闲
eUART_RX_RECV = 1, //接收数据
}eRX_STATE;
typedef struct _eUART_RX_{
eTX_STATE rx_state; //发送状态
u32 bound; //波特率
u8 nstop; //停止位数
}eUART_RX;
eUART_TX exUART_TX;
eUART_RX exUART_RX;
void Uart_Soft_Init(u32 Rate)
{
/*启动外设*/
INTDEV_SET_CLK_RST(GPIOA_BASE_ADDR,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV8));//24M
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
GPIO_SET_INPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN5),GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
exUART_TX.bound = Rate;
exUART_TX.nstop = 1;
exUART_TX.tx_state = eUART_TX_IDLE;
}
2.发送程序
/*** euart开始位 ***/
/*
* baud 波特率
*/
void Send_Start_Soft(eUART_TX *extx)
{
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_0(GPIOA_BASE_ADDR,(GPIO_PIN4));
delay_baud(extx->bound);
//GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN6));
}
/*** euar停止位 ***/
/*
* baud 波特率
* stop 停止位数
*/
void Send_Stop_Soft(eUART_TX *extx)
{
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
delay_baud(extx->bound);
}
/*** euart空闲 ***/
/*
* baud 波特率
* stop 停止位数
*/
void Send_Idle_Soft(eUART_TX *extx)
{
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
extx->tx_state = eUART_TX_IDLE; //空闲标志位置
}
//发送单个byte
void Send_Byte_Soft(unsigned char dat)
{
u8 i = 0;
while(exUART_TX.tx_state == eUART_TX_SEND); //等待总线空闲
if(exUART_TX.tx_state == eUART_TX_IDLE) //总线空闲
{
exUART_TX.tx_state = eUART_TX_SEND; //总线忙
Send_Start_Soft(&exUART_TX);
for(i = 0; i < 8; i++)
{
if(dat&0x01)
{
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
}
else
{
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_0(GPIOA_BASE_ADDR,(GPIO_PIN4));
}
dat = dat >> 1;
delay_baud(exUART_TX.bound);
}
Send_Stop_Soft(&exUART_TX);
}
Send_Idle_Soft(&exUART_TX);
}
//发送字符串
void Send_String_Soft(u8 *dat, u16 len)
{
u8 temp = 0;
u16 send_count = 0;
u8 i = 0;
while(send_count < len)
{
exUART_TX.tx_state = eUART_TX_SEND; //总线忙
temp = dat[send_count];
Send_Start_Soft(&exUART_TX);
for(i = 0; i < 8; i++)
{
if(temp&0x01)
{
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_1(GPIOA_BASE_ADDR,(GPIO_PIN4));
}
else
{
GPIO_SET_OUTPUT_EN_VALUE(GPIOA_BASE_ADDR,(GPIO_PIN4),GPIO_SET_ENABLE);
GPIO_SET_OUTPUT_PIN_TO_0(GPIOA_BASE_ADDR,(GPIO_PIN4));
}
temp = temp >> 1;
delay_baud(exUART_TX.bound);
}
send_count ++;
Send_Stop_Soft(&exUART_TX);
}
Send_Idle_Soft(&exUART_TX);
}
3.接收函数
u8 Recv_String_Soft(u8 *recv, u16 len)
{
u8 i = 0;
u16 recv_count = 0;
u8 dat = 0x00;
while(recv_count < len)
{
//等待RX拉低,接收数据起始位
while(((GPIO_GET_INPUT_VALUE_FAST(GPIOA_BASE_ADDR)&0x0020)>>5) != 0);
//接收到起始位,设置为接收繁忙,延时波特率时间
exUART_RX.rx_state = eUART_RX_RECV;
delay_baud(exUART_TX.bound);
NOP();
for(i = 0; i < 8; i ++)
{
dat = dat >> 1;
if(((GPIO_GET_INPUT_VALUE_FAST(GPIOA_BASE_ADDR)&0x0020) >> 5) == 1)
{
dat |= 0x80;
}
delay_baud(exUART_TX.bound);
}
recv[recv_count] = dat;
dat = 0;
recv_count ++;
delay_baud(exUART_TX.bound); //延时一个停止位时间
}
return recv_count;
}
4.延时函数
void delay_baud(u32 baud)
{
u32 start,stop,ticks;
start = CORE_CNT;
if(baud == 9600)
{
ticks = 5002;
}
else
{
//其他波特率对应延时自行添加
//ticks = (u32)(Sys_Clk * 1000000 / baud);
}
if(0xFFFFFFFF-start>=ticks){
stop=start+ticks;
while(CORE_CNT<stop && CORE_CNT>start){}
}
else{
stop=ticks-(0xFFFFFFFF-start);
while(CORE_CNT>start){}
while(CORE_CNT<stop){}
}
}
最终效果
*程序还有很多可以优化的地方,比如接收函数可以添加接收超时,此贴只作为一个DEMO,欢迎大家批评指正。
*也希望起到抛砖引玉的效果,能够看到更多优秀的程序开源。
离线
感谢分享,真是高产啊
离线
@XMGroupe.
补一个串口数据波形图,下图是1M波特率,每个bit占1us,8,N,1,低位先传。模拟串口改参数可以参照这个波形图自己写时序。
离线
文档说内部高速RC是200M, 低速是 8M, 这怎么说是 192M ?
离线
串口发送模拟还是比较简单的,STC都可以轻松做到,误码率都不高。但是串口接收模拟就不容易了,波特率高了就误码率高,然后中断太频繁对正常程序影响也大
离线