这与微控制器有关,但考虑将其发布在此处,因为它是算法和数据类型的问题,而不是任何硬件内容.我将解释这个问题,以便没有任何硬件知识的人仍然可以参加:)
在微控制器中,有一个10位分辨率的模数转换器.(它将输出0到1023之间的值)
我需要使用串口将此值发送到PC.
但是你一次只能写8位.(你需要写字节).这是微控制器的一个限制.
所以在上面的情况下至少我需要发送2个字节.
我的PC应用程序只读取一系列数字用于绘图.所以它应该捕获两个连续的字节并重新构建数字.但是在这里我们也需要一个分隔符.但是分隔符字符的ascii值在0到255之间,那么它会混淆该过程.
那么最简单的方法是什么?我应该将值作为一系列字符发送吗?
Ex : 1023 = "1""0""2""3" Vs "Char(255)Char(4)"
Run Code Online (Sandbox Code Playgroud)
总之,我需要以最快的方式在Serial上发送一个10位数的序列.:)
使用带有pic18f的Microchip C18编译器,我想在程序数据空间中创建一个3000字节的"大"缓冲区.
如果我把它放在main()(堆栈上):
char tab[127];
Run Code Online (Sandbox Code Playgroud)
我有这个错误:
Error [1300] stack frame too large
Run Code Online (Sandbox Code Playgroud)
如果我把它放在全局,我有这个错误:
Error - section '.udata_main.o' can not fit the section. Section '.udata_main.o' length=0x0000007f
Run Code Online (Sandbox Code Playgroud)
如何创建一个大缓冲区?你有关于如何使用c18管理pic18f上的大缓冲区的教程吗?
我在嵌入式项目中使用MIPS CPU(PIC32),但我开始质疑我的选择.我知道像MIPS这样的RISC CPU会生成比预期更多的指令,但我不认为它会是这样的.以下是反汇编列表中的代码段:
225: LATDSET = 0x0040;
sw s1,24808(s2)
sw s4,24808(s2)
sw s4,24808(s2)
sw s1,24808(s2)
sw s4,24808(s3)
sw s4,24808(s3)
sw s1,24808(s3)
226: {
227: porte = PORTE;
lw t1,24848(s4)
andi v0,t1,0xffff
lw v1,24848(s6)
andi ra,v1,0xffff
lw v1,24848(s6)
andi ra,v1,0xffff
lw v0,24848(s6)
andi t2,v0,0xffff
lw a2,24848(s5)
andi v1,a2,0xffff
lw t2,24848(s5)
andi v1,t2,0xffff
lw v0,24848(s5)
andi t2,v0,0xffff
228: if (porte & 0x0004)
andi t2,v0,0x4
andi s8,ra,0x4
andi s8,ra,0x4
andi ra,t2,0x4
andi a1,v1,0x4
andi a2,v1,0x4
andi a2,t2,0x4
229: pst_bytes_somi[0] |= sliding_bit;
or t3,t4,s0 …
Run Code Online (Sandbox Code Playgroud) 最近,我们一群(电子工程专业学生 - 英国)在PIC16F84A微控制器编程的基础上开始掌握这一点.需要将两个8位数相乘,每个都没有已知的最小值/最大值.一位同学提出了以下想法.
multiply_numbers:
; Takes numbers in Num1 and Num2, and returns product in OutH:OutL
clrf OutH ; clear all non-input variables
clrf OutL
mult_loop
bcf STATUS,c ; clear carry bit
movfw Num2
addwf OutL ; add Num2 to OutL
btfsc STATUS,c ; check carry bit
incf OutH ; if set, increment OutH
decfsz Num1 ; decrement Num1
goto mult_loop ; if Num1 is not zero, repeat loop
return ; else return
Run Code Online (Sandbox Code Playgroud)
我觉得这虽然在代码行方面很短,但执行大数字可能需要相对较长的时间.我自己做了一些思考,开始沿着向右移动一个数字,向左移动另一个数字的路线,并沿着路径向输出添加左移数字一定次数到达输出最终答案.我做得不对,但后来偶然发现了这个问题,这让我想到了一个输入数字:
N = a_0 …
如何使用小代码空间减少十六进制ASCII字符转换的代码空间?
在嵌入式应用程序中,我有非常有限的空间(注1).我需要将字节从串行I/O转换为ASCII值'0'到'9'和'A'到'F'到通常的十六进制值0到15.此外,所有其他240种组合,包括' a'到'f',需要被检测到(作为错误).
图书馆的功能,例如scanf(), atoi(), strtol()
是远太大而不能使用.
速度不是问题.代码大小是限制因素.
我现在的方法将256字节代码重新映射成256个代码,使得"0"到"9"和"A"到"Z"具有0到35的值.关于如何减少或不同方法的任何想法都是值得 赞赏的.
unsigned char ch = GetData(); // Fetch 1 byte of incoming data;
if (!(--ch & 64)) { // decrement, then if in the '0' to '9' area ...
ch = (ch + 7) & (~64); // move 0-9 next to A-Z codes
}
ch -= 54; // -= 'A' - 10 - 1
if (ch > 15) {
; // handle error …
Run Code Online (Sandbox Code Playgroud) void __attribute__((__interrupt__, no_auto_psv)) _T1Interrupt(void) // 5 Hz
Run Code Online (Sandbox Code Playgroud)
__attribute__
指令或宏来自 GCC,但__interrupt__
不是 no_auto_psv
,它特定于硬件。那么,GCC编译器是如何理解__interrupt__
的no_auoto_psv
,我搜索了一下,在其他地方没有找到任何声明。
那么基本上该_T1Interrupt
函数不带任何参数,也不返回任何内容,但具有上述属性?
我正在尝试为PIC18制作一个引导程序,所以我需要了解如何正确处理hex文件.例如,我理解如何处理以下十六行.
:040C0000E2EFFFF030
Run Code Online (Sandbox Code Playgroud)
04
:字节数
0C00
:十六进制数字的地址
00
:数据记录
E2EFFFF0
:数据序列
30
:校验和
所以我会知道如何处理上面的行,但是下面的十六行怎么样.
:020000040001F9
Run Code Online (Sandbox Code Playgroud)
02
:字节数
0000
: 地址
04
:扩展线性地址记录
0001
:数据
F9
:校验和
但究竟我该怎么做呢?我是否将这些数据写入该地址?你能把它翻译成机器语言吗?
顺便说一下,我的应用程序从地址开始,0c00
bootloader从地址开始,在0020
它上面是中断向量.谢谢!
更新
如果hex文件的第三行是以下,地址会FFC0
改变吗?
:10FFC000FF00FF00FF00FF00FF00FF000001E9EF5E
Run Code Online (Sandbox Code Playgroud)
我在想,因为hex文件的第二行有04
(扩展线性地址记录),那么我应该添加0001
到第三行的地址FFC0
,所以新地址就是这样的.
$0001 + $FFC0
将等于1FFC0
,所以第3行的下一组数据字节应写入此地址1FFC0
,这是正确的吗?
我试图使用pic24fj128gb206枚举usb cdc设备.设备似乎正确枚举.
但是当我将我的设备连接到Linux PC时,我从内核收到以下警告消息.
cdc_acm 1-8.1.6.7:1.0: failed to set dtr/rts
Run Code Online (Sandbox Code Playgroud)
当我尝试使用屏幕连接时,此消息将重复.
screen /dev/ttyACM9 115200
Run Code Online (Sandbox Code Playgroud)
我无法通过PC与我的设备通信[Ubuntu,14.04]
使用wireshark分析数据时,看起来USB通信正常,主机发出URB_CONTROL_out并且设备响应URB状态为 Broken Pipe (-EPIPE ) (-32)
任何人都可以帮我解决如何调试此问题或任何进一步调试的方法?
我是新编写的8位PIC固件,可以使用我的代码帮助.我将PIC16F1829用于获取RX命令的LED模块.我只是试图获得基本设置,如在RX引脚上接收到某个值时打开LED,但是甚至无法实现.
想让UART通过中断工作,但是甚至无法在主循环中使用轮询.我的中断向量在下面的代码中被注释掉了.
RX引脚:RC5
TX引脚:RB7
用于打开和关闭LED的引脚:RA5
引脚RA5工作正常,可以打开和关闭LED.TX引脚工作正常,但我还没有确认中断TXIF是否也不起作用,就像RCIF不能正常工作一样.
我试过读RCIF和PIR1bits.RCIF.他们都编译了.两个人都没有工作.我在两个不同的LED模块上尝试了两个不同的PIC.它们打开,但读取RX引脚也不起作用.
变量RXIN最初被定义为3,因此由于主循环内的RXIN--循环,灯在启动时闪烁3次,所以我知道它正在进入主循环.但据我所知,RCIF中断在RX引脚接收时没有触发.
我已经在示波器上确认使用相同的波特率将信号送入RX和TX引脚,因此我认为波特率配置正确(300波特,8N1.)我还在示波器上确认RX引脚接收到强而干净的5V信号.到目前为止,轮询RCIF或使用中断服务路由都没有奏效.如果有人能够看到我没有看到的代码问题,我们将非常感谢您的帮助.
我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
// This is for 300 baud rate
#define _BAUD_PRESCALER_LOW_ 0x2A
#define _BAUD_PRESCALER_HIGH_ 0x68
#define _XTAL_FREQ 32000000
#pragma config FOSC = INTOSC // Oscillator Selection->INTOSC oscillator: I/O function on CLKIN pin
#pragma config WDTE = OFF // Watchdog Timer Enable->WDT enabled
#pragma config PWRTE = OFF // Power-up Timer Enable->PWRT disabled
#pragma config MCLRE = OFF // MCLR Pin Function Select->MCLR/VPP pin function is digital …
Run Code Online (Sandbox Code Playgroud) 我对使用 PIC 芯片比较陌生,所以这可能是一个新手级别的问题,但我正在尝试编写一个头文件,其中包含所有 I/O 端口的 TRIS/ODC/INIT 掩码.
在内置该芯片的 PCB 上,任何给定组件都可能使用来自多个端口的引脚,并且可能有十几个单独的组件需要详细评论。例如,与特定 SPI ADC 模块的接口使用来自端口 A、D 和 F 的引脚。
对我来说,编写此文件的读者友好的方式似乎是按组件组织文件,以便读者一目了然地知道正在使用哪些引脚,它们是配置为输入还是输出,以及它们是如何初始化的。
例如,仅显示 TRIS 掩码信息,以下是我用来演示我正在谈论的特定 ADC 模块的一段代码:
#define PORTD_TRIS_MASK 0x00
#define PORTF_TRIS_MASK 0x00
// ...
// lots of hardware configuration stuff goes here
// ...
// ANALOG INPUT - THERMOCOUPLE 1
// Thermocouple ADC chip MAX31856 DNP communicates over SPI
// Accepts any type of thermocouple
// TC1_CS pulled high
// TC1_DRDY pulled high
#define TC1_MOSI LATAbits.LATA14
#define TC1_MISO PORTDbits.RD10
#define TC1_SCK LATDbits.LATD11
#define …
Run Code Online (Sandbox Code Playgroud)